
(function () {

    var EXTUTIL = Ext.util,
    EACH = Ext.each,
    TRUE = true,
    FALSE = false;

    EXTUTIL.Observable = function () {

        var me = this, e = me.events;
        if (me.listeners) {
            me.on(me.listeners);
            delete me.listeners;
        }
        me.events = e || {};
    };

    EXTUTIL.Observable.prototype = {

        filterOptRe: /^(?:scope|delay|buffer|single)$/,


        fireEvent: function () {
            var a = Array.prototype.slice.call(arguments, 0),
            ename = a[0].toLowerCase(),
            me = this,
            ret = TRUE,
            ce = me.events[ename],
            cc,
            q,
            c;
            if (me.eventsSuspended === TRUE) {
                if (q = me.eventQueue) {
                    q.push(a);
                }
            }
            else if (typeof ce == 'object') {
                if (ce.bubble) {
                    if (ce.fire.apply(ce, a.slice(1)) === FALSE) {
                        return FALSE;
                    }
                    c = me.getBubbleTarget && me.getBubbleTarget();
                    if (c && c.enableBubble) {
                        cc = c.events[ename];
                        if (!cc || typeof cc != 'object' || !cc.bubble) {
                            c.enableBubble(ename);
                        }
                        return c.fireEvent.apply(c, a);
                    }
                }
                else {
                    a.shift();
                    ret = ce.fire.apply(ce, a);
                }
            }
            return ret;
        },


        addListener: function (eventName, fn, scope, o) {
            var me = this,
            e,
            oe,
            ce;

            if (typeof eventName == 'object') {
                o = eventName;
                for (e in o) {
                    oe = o[e];
                    if (!me.filterOptRe.test(e)) {
                        me.addListener(e, oe.fn || oe, oe.scope || o.scope, oe.fn ? oe : o);
                    }
                }
            } else {
                eventName = eventName.toLowerCase();
                ce = me.events[eventName] || TRUE;
                if (typeof ce == 'boolean') {
                    me.events[eventName] = ce = new EXTUTIL.Event(me, eventName);
                }
                ce.addListener(fn, scope, typeof o == 'object' ? o : {});
            }
        },


        removeListener: function (eventName, fn, scope) {
            var ce = this.events[eventName.toLowerCase()];
            if (typeof ce == 'object') {
                ce.removeListener(fn, scope);
            }
        },


        purgeListeners: function () {
            var events = this.events,
            evt,
            key;
            for (key in events) {
                evt = events[key];
                if (typeof evt == 'object') {
                    evt.clearListeners();
                }
            }
        },


        addEvents: function (o) {
            var me = this;
            me.events = me.events || {};
            if (typeof o == 'string') {
                var a = arguments,
                i = a.length;
                while (i--) {
                    me.events[a[i]] = me.events[a[i]] || TRUE;
                }
            } else {
                Ext.applyIf(me.events, o);
            }
        },


        hasListener: function (eventName) {
            var e = this.events[eventName.toLowerCase()];
            return typeof e == 'object' && e.listeners.length > 0;
        },


        suspendEvents: function (queueSuspended) {
            this.eventsSuspended = TRUE;
            if (queueSuspended && !this.eventQueue) {
                this.eventQueue = [];
            }
        },


        resumeEvents: function () {
            var me = this,
            queued = me.eventQueue || [];
            me.eventsSuspended = FALSE;
            delete me.eventQueue;
            EACH(queued, function (e) {
                me.fireEvent.apply(me, e);
            });
        }
    };

    var OBSERVABLE = EXTUTIL.Observable.prototype;

    OBSERVABLE.on = OBSERVABLE.addListener;

    OBSERVABLE.un = OBSERVABLE.removeListener;


    EXTUTIL.Observable.releaseCapture = function (o) {
        o.fireEvent = OBSERVABLE.fireEvent;
    };

    function createTargeted(h, o, scope) {
        return function () {
            if (o.target == arguments[0]) {
                h.apply(scope, Array.prototype.slice.call(arguments, 0));
            }
        };
    };

    function createBuffered(h, o, l, scope) {
        l.task = new EXTUTIL.DelayedTask();
        return function () {
            l.task.delay(o.buffer, h, scope, Array.prototype.slice.call(arguments, 0));
        };
    };

    function createSingle(h, e, fn, scope) {
        return function () {
            e.removeListener(fn, scope);
            return h.apply(scope, arguments);
        };
    };

    function createDelayed(h, o, l, scope) {
        return function () {
            var task = new EXTUTIL.DelayedTask(),
            args = Array.prototype.slice.call(arguments, 0);
            if (!l.tasks) {
                l.tasks = [];
            }
            l.tasks.push(task);
            task.delay(o.delay || 10, function () {
                l.tasks.remove(task);
                h.apply(scope, args);
            }, scope);
        };
    };

    EXTUTIL.Event = function (obj, name) {
        this.name = name;
        this.obj = obj;
        this.listeners = [];
    };

    EXTUTIL.Event.prototype = {
        addListener: function (fn, scope, options) {
            var me = this,
            l;
            scope = scope || me.obj;
            if (!me.isListening(fn, scope)) {
                l = me.createListener(fn, scope, options);
                if (me.firing) {
                    me.listeners = me.listeners.slice(0);
                }
                me.listeners.push(l);
            }
        },

        createListener: function (fn, scope, o) {
            o = o || {};
            scope = scope || this.obj;
            var l = {
                fn: fn,
                scope: scope,
                options: o
            }, h = fn;
            if (o.target) {
                h = createTargeted(h, o, scope);
            }
            if (o.delay) {
                h = createDelayed(h, o, l, scope);
            }
            if (o.single) {
                h = createSingle(h, this, fn, scope);
            }
            if (o.buffer) {
                h = createBuffered(h, o, l, scope);
            }
            l.fireFn = h;
            return l;
        },

        findListener: function (fn, scope) {
            var list = this.listeners,
            i = list.length,
            l;

            scope = scope || this.obj;
            while (i--) {
                l = list[i];
                if (l) {
                    if (l.fn == fn && l.scope == scope) {
                        return i;
                    }
                }
            }
            return -1;
        },

        isListening: function (fn, scope) {
            return this.findListener(fn, scope) != -1;
        },

        removeListener: function (fn, scope) {
            var index,
            l,
            k,
            me = this,
            ret = FALSE;
            if ((index = me.findListener(fn, scope)) != -1) {
                if (me.firing) {
                    me.listeners = me.listeners.slice(0);
                }
                l = me.listeners[index];
                if (l.task) {
                    l.task.cancel();
                    delete l.task;
                }
                k = l.tasks && l.tasks.length;
                if (k) {
                    while (k--) {
                        l.tasks[k].cancel();
                    }
                    delete l.tasks;
                }
                me.listeners.splice(index, 1);
                ret = TRUE;
            }
            return ret;
        },


        clearListeners: function () {
            var me = this,
            l = me.listeners,
            i = l.length;
            while (i--) {
                me.removeListener(l[i].fn, l[i].scope);
            }
        },

        fire: function () {
            var me = this,
            listeners = me.listeners,
            len = listeners.length,
            i = 0,
            l;

            if (len > 0) {
                me.firing = TRUE;
                var args = Array.prototype.slice.call(arguments, 0);
                for (; i < len; i++) {
                    l = listeners[i];
                    if (l && l.fireFn.apply(l.scope || me.obj || window, args) === FALSE) {
                        return (me.firing = FALSE);
                    }
                }
            }
            me.firing = FALSE;
            return TRUE;
        }

    };
})();

Ext.DomHelper = function () {
    var tempTableEl = null,
        emptyTags = /^(?:br|frame|hr|img|input|link|meta|range|spacer|wbr|area|param|col)$/i,
        tableRe = /^table|tbody|tr|td$/i,
        confRe = /tag|children|cn|html$/i,
        tableElRe = /td|tr|tbody/i,
        cssRe = /([a-z0-9-]+)\s*:\s*([^;\s]+(?:\s*[^;\s]+)*);?/gi,
        endRe = /end/i,
        pub,

        afterbegin = 'afterbegin',
        afterend = 'afterend',
        beforebegin = 'beforebegin',
        beforeend = 'beforeend',
        ts = '<table>',
        te = '</table>',
        tbs = ts + '<tbody>',
        tbe = '</tbody>' + te,
        trs = tbs + '<tr>',
        tre = '</tr>' + tbe;


    function doInsert(el, o, returnElement, pos, sibling, append) {
        var newNode = pub.insertHtml(pos, Ext.getDom(el), createHtml(o));
        return returnElement ? Ext.get(newNode, true) : newNode;
    }


    function createHtml(o) {
        var b = '',
            attr,
            val,
            key,
            cn;

        if (typeof o == "string") {
            b = o;
        } else if (Ext.isArray(o)) {
            for (var i = 0; i < o.length; i++) {
                if (o[i]) {
                    b += createHtml(o[i]);
                }
            };
        } else {
            b += '<' + (o.tag = o.tag || 'div');
            for (attr in o) {
                val = o[attr];
                if (!confRe.test(attr)) {
                    if (typeof val == "object") {
                        b += ' ' + attr + '="';
                        for (key in val) {
                            b += key + ':' + val[key] + ';';
                        };
                        b += '"';
                    } else {
                        b += ' ' + ({ cls: 'class', htmlFor: 'for'}[attr] || attr) + '="' + val + '"';
                    }
                }
            };

            if (emptyTags.test(o.tag)) {
                b += '/>';
            } else {
                b += '>';
                if ((cn = o.children || o.cn)) {
                    b += createHtml(cn);
                } else if (o.html) {
                    b += o.html;
                }
                b += '</' + o.tag + '>';
            }
        }
        return b;
    }

    function ieTable(depth, s, h, e) {
        tempTableEl.innerHTML = [s, h, e].join('');
        var i = -1,
            el = tempTableEl,
            ns;
        while (++i < depth) {
            el = el.firstChild;
        }

        if (ns = el.nextSibling) {
            var df = document.createDocumentFragment();
            while (el) {
                ns = el.nextSibling;
                df.appendChild(el);
                el = ns;
            }
            el = df;
        }
        return el;
    }


    function insertIntoTable(tag, where, el, html) {
        var node,
            before;

        tempTableEl = tempTableEl || document.createElement('div');

        if (tag == 'td' && (where == afterbegin || where == beforeend) ||
           !tableElRe.test(tag) && (where == beforebegin || where == afterend)) {
            return;
        }
        before = where == beforebegin ? el :
                 where == afterend ? el.nextSibling :
                 where == afterbegin ? el.firstChild : null;

        if (where == beforebegin || where == afterend) {
            el = el.parentNode;
        }

        if (tag == 'td' || (tag == 'tr' && (where == beforeend || where == afterbegin))) {
            node = ieTable(4, trs, html, tre);
        } else if ((tag == 'tbody' && (where == beforeend || where == afterbegin)) ||
                   (tag == 'tr' && (where == beforebegin || where == afterend))) {
            node = ieTable(3, tbs, html, tbe);
        } else {
            node = ieTable(2, ts, html, te);
        }
        el.insertBefore(node, before);
        return node;
    }


    pub = {

        markup: function (o) {
            return createHtml(o);
        },


        applyStyles: function (el, styles) {
            if (styles) {
                var matches;

                el = Ext.fly(el);
                if (typeof styles == "function") {
                    styles = styles.call();
                }
                if (typeof styles == "string") {

                    cssRe.lastIndex = 0;
                    while ((matches = cssRe.exec(styles))) {
                        el.setStyle(matches[1], matches[2]);
                    }
                } else if (typeof styles == "object") {
                    el.setStyle(styles);
                }
            }
        },


        insertHtml: function (where, el, html) {
            var hash = {},
                hashVal,
                setStart,
                range,
                frag,
                rangeEl,
                rs;

            where = where.toLowerCase();

            hash[beforebegin] = ['BeforeBegin', 'previousSibling'];
            hash[afterend] = ['AfterEnd', 'nextSibling'];

            if (el.insertAdjacentHTML) {
                if (tableRe.test(el.tagName) && (rs = insertIntoTable(el.tagName.toLowerCase(), where, el, html))) {
                    return rs;
                }

                hash[afterbegin] = ['AfterBegin', 'firstChild'];
                hash[beforeend] = ['BeforeEnd', 'lastChild'];
                if ((hashVal = hash[where])) {
                    el.insertAdjacentHTML(hashVal[0], html);
                    return el[hashVal[1]];
                }
            } else {
                range = el.ownerDocument.createRange();
                setStart = 'setStart' + (endRe.test(where) ? 'After' : 'Before');
                if (hash[where]) {
                    range[setStart](el);
                    frag = range.createContextualFragment(html);
                    el.parentNode.insertBefore(frag, where == beforebegin ? el : el.nextSibling);
                    return el[(where == beforebegin ? 'previous' : 'next') + 'Sibling'];
                } else {
                    rangeEl = (where == afterbegin ? 'first' : 'last') + 'Child';
                    if (el.firstChild) {
                        range[setStart](el[rangeEl]);
                        frag = range.createContextualFragment(html);
                        if (where == afterbegin) {
                            el.insertBefore(frag, el.firstChild);
                        } else {
                            el.appendChild(frag);
                        }
                    } else {
                        el.innerHTML = html;
                    }
                    return el[rangeEl];
                }
            }
            throw 'Illegal insertion point -> "' + where + '"';
        },


        insertBefore: function (el, o, returnElement) {
            return doInsert(el, o, returnElement, beforebegin);
        },


        insertAfter: function (el, o, returnElement) {
            return doInsert(el, o, returnElement, afterend, 'nextSibling');
        },


        insertFirst: function (el, o, returnElement) {
            return doInsert(el, o, returnElement, afterbegin, 'firstChild');
        },


        append: function (el, o, returnElement) {
            return doInsert(el, o, returnElement, beforeend, '', true);
        },


        overwrite: function (el, o, returnElement) {
            el = Ext.getDom(el);
            el.innerHTML = createHtml(o);
            return returnElement ? Ext.get(el.firstChild) : el.firstChild;
        },

        createHtml: createHtml
    };
    return pub;
} ();

Ext.Template = function (html) {
    var me = this,
        a = arguments,
        buf = [],
        v;

    if (Ext.isArray(html)) {
        html = html.join("");
    } else if (a.length > 1) {
        for (var i = 0, len = a.length; i < len; i++) {
            v = a[i];
            if (typeof v == 'object') {
                Ext.apply(me, v);
            } else {
                buf.push(v);
            }
        };
        html = buf.join('');
    }


    me.html = html;

    if (me.compiled) {
        me.compile();
    }
};
Ext.Template.prototype = {

    re: /\{([\w-]+)\}/g,



    applyTemplate: function (values) {
        var me = this;

        return me.compiled ?
                me.compiled(values) :
                me.html.replace(me.re, function (m, name) {
                    return values[name] !== undefined ? values[name] : "";
                });
    },


    set: function (html, compile) {
        var me = this;
        me.html = html;
        me.compiled = null;
        return compile ? me.compile() : me;
    },


    compile: function () {
        var me = this,
            sep = Ext.isGecko ? "+" : ",";

        function fn(m, name) {
            name = "values['" + name + "']";
            return "'" + sep + '(' + name + " == undefined ? '' : " + name + ')' + sep + "'";
        }

        eval("this.compiled = function(values){ return " + (Ext.isGecko ? "'" : "['") +
             me.html.replace(/\\/g, '\\\\').replace(/(\r\n|\n)/g, '\\n').replace(/'/g, "\\'").replace(this.re, fn) +
             (Ext.isGecko ? "';};" : "'].join('');};"));
        return me;
    },


    insertFirst: function (el, values, returnElement) {
        return this.doInsert('afterBegin', el, values, returnElement);
    },


    insertBefore: function (el, values, returnElement) {
        return this.doInsert('beforeBegin', el, values, returnElement);
    },


    insertAfter: function (el, values, returnElement) {
        return this.doInsert('afterEnd', el, values, returnElement);
    },


    append: function (el, values, returnElement) {
        return this.doInsert('beforeEnd', el, values, returnElement);
    },

    doInsert: function (where, el, values, returnEl) {
        el = Ext.getDom(el);
        var newNode = Ext.DomHelper.insertHtml(where, el, this.applyTemplate(values));
        return returnEl ? Ext.get(newNode, true) : newNode;
    },


    overwrite: function (el, values, returnElement) {
        el = Ext.getDom(el);
        el.innerHTML = this.applyTemplate(values);
        return returnElement ? Ext.get(el.firstChild, true) : el.firstChild;
    }
};

Ext.Template.prototype.apply = Ext.Template.prototype.applyTemplate;


Ext.Template.from = function (el, config) {
    el = Ext.getDom(el);
    return new Ext.Template(el.value || el.innerHTML, config || '');
};


Ext.DomQuery = function () {
    var cache = {},
    	simpleCache = {},
    	valueCache = {},
    	nonSpace = /\S/,
    	trimRe = /^\s+|\s+$/g,
    	tplRe = /\{(\d+)\}/g,
    	modeRe = /^(\s?[\/>+~]\s?|\s|$)/,
    	tagTokenRe = /^(#)?([\w-\*]+)/,
    	nthRe = /(\d*)n\+?(\d*)/,
    	nthRe2 = /\D/,



	isIE = window.ActiveXObject ? true : false,
	key = 30803;



    eval("var batch = 30803;");



    function child(parent, index) {
        var i = 0,
            n = parent.firstChild;
        while (n) {
            if (n.nodeType == 1) {
                if (++i == index) {
                    return n;
                }
            }
            n = n.nextSibling;
        }
        return null;
    }


    function next(n) {
        while ((n = n.nextSibling) && n.nodeType != 1);
        return n;
    }


    function prev(n) {
        while ((n = n.previousSibling) && n.nodeType != 1);
        return n;
    }



    function children(parent) {
        var n = parent.firstChild,
	    nodeIndex = -1,
	    nextNode;
        while (n) {
            nextNode = n.nextSibling;

            if (n.nodeType == 3 && !nonSpace.test(n.nodeValue)) {
                parent.removeChild(n);
            } else {

                n.nodeIndex = ++nodeIndex;
            }
            n = nextNode;
        }
        return this;
    }




    function byClassName(nodeSet, cls) {
        if (!cls) {
            return nodeSet;
        }
        var result = [], ri = -1;
        for (var i = 0, ci; ci = nodeSet[i]; i++) {
            if ((' ' + ci.className + ' ').indexOf(cls) != -1) {
                result[++ri] = ci;
            }
        }
        return result;
    };

    function attrValue(n, attr) {

        if (!n.tagName && typeof n.length != "undefined") {
            n = n[0];
        }
        if (!n) {
            return null;
        }

        if (attr == "for") {
            return n.htmlFor;
        }
        if (attr == "class" || attr == "className") {
            return n.className;
        }
        return n.getAttribute(attr) || n[attr];

    };





    function getNodes(ns, mode, tagName) {
        var result = [], ri = -1, cs;
        if (!ns) {
            return result;
        }
        tagName = tagName || "*";

        if (typeof ns.getElementsByTagName != "undefined") {
            ns = [ns];
        }



        if (!mode) {
            for (var i = 0, ni; ni = ns[i]; i++) {
                cs = ni.getElementsByTagName(tagName);
                for (var j = 0, ci; ci = cs[j]; j++) {
                    result[++ri] = ci;
                }
            }


        } else if (mode == "/" || mode == ">") {
            var utag = tagName.toUpperCase();
            for (var i = 0, ni, cn; ni = ns[i]; i++) {
                cn = ni.childNodes;
                for (var j = 0, cj; cj = cn[j]; j++) {
                    if (cj.nodeName == utag || cj.nodeName == tagName || tagName == '*') {
                        result[++ri] = cj;
                    }
                }
            }


        } else if (mode == "+") {
            var utag = tagName.toUpperCase();
            for (var i = 0, n; n = ns[i]; i++) {
                while ((n = n.nextSibling) && n.nodeType != 1);
                if (n && (n.nodeName == utag || n.nodeName == tagName || tagName == '*')) {
                    result[++ri] = n;
                }
            }


        } else if (mode == "~") {
            var utag = tagName.toUpperCase();
            for (var i = 0, n; n = ns[i]; i++) {
                while ((n = n.nextSibling)) {
                    if (n.nodeName == utag || n.nodeName == tagName || tagName == '*') {
                        result[++ri] = n;
                    }
                }
            }
        }
        return result;
    }

    function concat(a, b) {
        if (b.slice) {
            return a.concat(b);
        }
        for (var i = 0, l = b.length; i < l; i++) {
            a[a.length] = b[i];
        }
        return a;
    }

    function byTag(cs, tagName) {
        if (cs.tagName || cs == document) {
            cs = [cs];
        }
        if (!tagName) {
            return cs;
        }
        var result = [], ri = -1;
        tagName = tagName.toLowerCase();
        for (var i = 0, ci; ci = cs[i]; i++) {
            if (ci.nodeType == 1 && ci.tagName.toLowerCase() == tagName) {
                result[++ri] = ci;
            }
        }
        return result;
    }

    function byId(cs, id) {
        if (cs.tagName || cs == document) {
            cs = [cs];
        }
        if (!id) {
            return cs;
        }
        var result = [], ri = -1;
        for (var i = 0, ci; ci = cs[i]; i++) {
            if (ci && ci.id == id) {
                result[++ri] = ci;
                return result;
            }
        }
        return result;
    }



    function byAttribute(cs, attr, value, op, custom) {
        var result = [],
            ri = -1,
            useGetStyle = custom == "{",
            fn = Ext.DomQuery.operators[op],
            a,
            xml,
            hasXml;

        for (var i = 0, ci; ci = cs[i]; i++) {

            if (ci.nodeType != 1) {
                continue;
            }

            if (!hasXml) {
                xml = Ext.DomQuery.isXml(ci);
                hasXml = true;
            }


            if (!xml) {
                if (useGetStyle) {
                    a = Ext.DomQuery.getStyle(ci, attr);
                } else if (attr == "class" || attr == "className") {
                    a = ci.className;
                } else if (attr == "for") {
                    a = ci.htmlFor;
                } else if (attr == "href") {


                    a = ci.getAttribute("href", 2);
                } else {
                    a = ci.getAttribute(attr);
                }
            } else {
                a = ci.getAttribute(attr);
            }
            if ((fn && fn(a, value)) || (!fn && a)) {
                result[++ri] = ci;
            }
        }
        return result;
    }

    function byPseudo(cs, name, value) {
        return Ext.DomQuery.pseudos[name](cs, value);
    }

    function nodupIEXml(cs) {
        var d = ++key,
            r;
        cs[0].setAttribute("_nodup", d);
        r = [cs[0]];
        for (var i = 1, len = cs.length; i < len; i++) {
            var c = cs[i];
            if (!c.getAttribute("_nodup") != d) {
                c.setAttribute("_nodup", d);
                r[r.length] = c;
            }
        }
        for (var i = 0, len = cs.length; i < len; i++) {
            cs[i].removeAttribute("_nodup");
        }
        return r;
    }

    function nodup(cs) {
        if (!cs) {
            return [];
        }
        var len = cs.length, c, i, r = cs, cj, ri = -1;
        if (!len || typeof cs.nodeType != "undefined" || len == 1) {
            return cs;
        }
        if (isIE && typeof cs[0].selectSingleNode != "undefined") {
            return nodupIEXml(cs);
        }
        var d = ++key;
        cs[0]._nodup = d;
        for (i = 1; c = cs[i]; i++) {
            if (c._nodup != d) {
                c._nodup = d;
            } else {
                r = [];
                for (var j = 0; j < i; j++) {
                    r[++ri] = cs[j];
                }
                for (j = i + 1; cj = cs[j]; j++) {
                    if (cj._nodup != d) {
                        cj._nodup = d;
                        r[++ri] = cj;
                    }
                }
                return r;
            }
        }
        return r;
    }

    function quickDiffIEXml(c1, c2) {
        var d = ++key,
            r = [];
        for (var i = 0, len = c1.length; i < len; i++) {
            c1[i].setAttribute("_qdiff", d);
        }
        for (var i = 0, len = c2.length; i < len; i++) {
            if (c2[i].getAttribute("_qdiff") != d) {
                r[r.length] = c2[i];
            }
        }
        for (var i = 0, len = c1.length; i < len; i++) {
            c1[i].removeAttribute("_qdiff");
        }
        return r;
    }

    function quickDiff(c1, c2) {
        var len1 = c1.length,
        	d = ++key,
        	r = [];
        if (!len1) {
            return c2;
        }
        if (isIE && typeof c1[0].selectSingleNode != "undefined") {
            return quickDiffIEXml(c1, c2);
        }
        for (var i = 0; i < len1; i++) {
            c1[i]._qdiff = d;
        }
        for (var i = 0, len = c2.length; i < len; i++) {
            if (c2[i]._qdiff != d) {
                r[r.length] = c2[i];
            }
        }
        return r;
    }

    function quickId(ns, mode, root, id) {
        if (ns == root) {
            var d = root.ownerDocument || root;
            return d.getElementById(id);
        }
        ns = getNodes(ns, mode, "*");
        return byId(ns, id);
    }

    return {
        getStyle: function (el, name) {
            return Ext.fly(el).getStyle(name);
        },

        compile: function (path, type) {
            type = type || "select";


            var fn = ["var f = function(root){\n var mode; ++batch; var n = root || document;\n"],
        		mode,
        		lastPath,
            	matchers = Ext.DomQuery.matchers,
            	matchersLn = matchers.length,
            	modeMatch,

            	lmode = path.match(modeRe);

            if (lmode && lmode[1]) {
                fn[fn.length] = 'mode="' + lmode[1].replace(trimRe, "") + '";';
                path = path.replace(lmode[1], "");
            }


            while (path.substr(0, 1) == "/") {
                path = path.substr(1);
            }

            while (path && lastPath != path) {
                lastPath = path;
                var tokenMatch = path.match(tagTokenRe);
                if (type == "select") {
                    if (tokenMatch) {

                        if (tokenMatch[1] == "#") {
                            fn[fn.length] = 'n = quickId(n, mode, root, "' + tokenMatch[2] + '");';
                        } else {
                            fn[fn.length] = 'n = getNodes(n, mode, "' + tokenMatch[2] + '");';
                        }
                        path = path.replace(tokenMatch[0], "");
                    } else if (path.substr(0, 1) != '@') {
                        fn[fn.length] = 'n = getNodes(n, mode, "*");';
                    }

                } else {
                    if (tokenMatch) {
                        if (tokenMatch[1] == "#") {
                            fn[fn.length] = 'n = byId(n, "' + tokenMatch[2] + '");';
                        } else {
                            fn[fn.length] = 'n = byTag(n, "' + tokenMatch[2] + '");';
                        }
                        path = path.replace(tokenMatch[0], "");
                    }
                }
                while (!(modeMatch = path.match(modeRe))) {
                    var matched = false;
                    for (var j = 0; j < matchersLn; j++) {
                        var t = matchers[j];
                        var m = path.match(t.re);
                        if (m) {
                            fn[fn.length] = t.select.replace(tplRe, function (x, i) {
                                return m[i];
                            });
                            path = path.replace(m[0], "");
                            matched = true;
                            break;
                        }
                    }

                    if (!matched) {
                        throw 'Error parsing selector, parsing failed at "' + path + '"';
                    }
                }
                if (modeMatch[1]) {
                    fn[fn.length] = 'mode="' + modeMatch[1].replace(trimRe, "") + '";';
                    path = path.replace(modeMatch[1], "");
                }
            }

            fn[fn.length] = "return nodup(n);\n}";


            eval(fn.join(""));
            return f;
        },


        jsSelect: function (path, root, type) {

            root = root || document;

            if (typeof root == "string") {
                root = document.getElementById(root);
            }
            var paths = path.split(","),
            	results = [];


            for (var i = 0, len = paths.length; i < len; i++) {
                var subPath = paths[i].replace(trimRe, "");

                if (!cache[subPath]) {
                    cache[subPath] = Ext.DomQuery.compile(subPath);
                    if (!cache[subPath]) {
                        throw subPath + " is not a valid selector";
                    }
                }
                var result = cache[subPath](root);
                if (result && result != document) {
                    results = results.concat(result);
                }
            }



            if (paths.length > 1) {
                return nodup(results);
            }
            return results;
        },
        isXml: function (el) {
            var docEl = (el ? el.ownerDocument || el : 0).documentElement;
            return docEl ? docEl.nodeName !== "HTML" : false;
        },
        select: document.querySelectorAll ? function (path, root, type) {
            root = root || document;
            if (!Ext.DomQuery.isXml(root)) {
                try {
                    var cs = root.querySelectorAll(path);
                    return Ext.toArray(cs);
                }
                catch (ex) { }
            }
            return Ext.DomQuery.jsSelect.call(this, path, root, type);
        } : function (path, root, type) {
            return Ext.DomQuery.jsSelect.call(this, path, root, type);
        },


        selectNode: function (path, root) {
            return Ext.DomQuery.select(path, root)[0];
        },


        selectValue: function (path, root, defaultValue) {
            path = path.replace(trimRe, "");
            if (!valueCache[path]) {
                valueCache[path] = Ext.DomQuery.compile(path, "select");
            }
            var n = valueCache[path](root), v;
            n = n[0] ? n[0] : n;





            if (typeof n.normalize == 'function') n.normalize();

            v = (n && n.firstChild ? n.firstChild.nodeValue : null);
            return ((v === null || v === undefined || v === '') ? defaultValue : v);
        },


        selectNumber: function (path, root, defaultValue) {
            var v = Ext.DomQuery.selectValue(path, root, defaultValue || 0);
            return parseFloat(v);
        },


        is: function (el, ss) {
            if (typeof el == "string") {
                el = document.getElementById(el);
            }
            var isArray = Ext.isArray(el),
            	result = Ext.DomQuery.filter(isArray ? el : [el], ss);
            return isArray ? (result.length == el.length) : (result.length > 0);
        },


        filter: function (els, ss, nonMatches) {
            ss = ss.replace(trimRe, "");
            if (!simpleCache[ss]) {
                simpleCache[ss] = Ext.DomQuery.compile(ss, "simple");
            }
            var result = simpleCache[ss](els);
            return nonMatches ? quickDiff(result, els) : result;
        },


        matchers: [{
            re: /^\.([\w-]+)/,
            select: 'n = byClassName(n, " {1} ");'
        }, {
            re: /^\:([\w-]+)(?:\(((?:[^\s>\/]*|.*?))\))?/,
            select: 'n = byPseudo(n, "{1}", "{2}");'
        }, {
            re: /^(?:([\[\{])(?:@)?([\w-]+)\s?(?:(=|.=)\s?['"]?(.*?)["']?)?[\]\}])/,
            select: 'n = byAttribute(n, "{2}", "{4}", "{3}", "{1}");'
        }, {
            re: /^#([\w-]+)/,
            select: 'n = byId(n, "{1}");'
        }, {
            re: /^@([\w-]+)/,
            select: 'return {firstChild:{nodeValue:attrValue(n, "{1}")}};'
        }
        ],


        operators: {
            "=": function (a, v) {
                return a == v;
            },
            "!=": function (a, v) {
                return a != v;
            },
            "^=": function (a, v) {
                return a && a.substr(0, v.length) == v;
            },
            "$=": function (a, v) {
                return a && a.substr(a.length - v.length) == v;
            },
            "*=": function (a, v) {
                return a && a.indexOf(v) !== -1;
            },
            "%=": function (a, v) {
                return (a % v) == 0;
            },
            "|=": function (a, v) {
                return a && (a == v || a.substr(0, v.length + 1) == v + '-');
            },
            "~=": function (a, v) {
                return a && (' ' + a + ' ').indexOf(' ' + v + ' ') != -1;
            }
        },


        pseudos: {
            "first-child": function (c) {
                var r = [], ri = -1, n;
                for (var i = 0, ci; ci = n = c[i]; i++) {
                    while ((n = n.previousSibling) && n.nodeType != 1);
                    if (!n) {
                        r[++ri] = ci;
                    }
                }
                return r;
            },

            "last-child": function (c) {
                var r = [], ri = -1, n;
                for (var i = 0, ci; ci = n = c[i]; i++) {
                    while ((n = n.nextSibling) && n.nodeType != 1);
                    if (!n) {
                        r[++ri] = ci;
                    }
                }
                return r;
            },

            "nth-child": function (c, a) {
                var r = [], ri = -1,
                	m = nthRe.exec(a == "even" && "2n" || a == "odd" && "2n+1" || !nthRe2.test(a) && "n+" + a || a),
                	f = (m[1] || 1) - 0, l = m[2] - 0;
                for (var i = 0, n; n = c[i]; i++) {
                    var pn = n.parentNode;
                    if (batch != pn._batch) {
                        var j = 0;
                        for (var cn = pn.firstChild; cn; cn = cn.nextSibling) {
                            if (cn.nodeType == 1) {
                                cn.nodeIndex = ++j;
                            }
                        }
                        pn._batch = batch;
                    }
                    if (f == 1) {
                        if (l == 0 || n.nodeIndex == l) {
                            r[++ri] = n;
                        }
                    } else if ((n.nodeIndex + l) % f == 0) {
                        r[++ri] = n;
                    }
                }

                return r;
            },

            "only-child": function (c) {
                var r = [], ri = -1; ;
                for (var i = 0, ci; ci = c[i]; i++) {
                    if (!prev(ci) && !next(ci)) {
                        r[++ri] = ci;
                    }
                }
                return r;
            },

            "empty": function (c) {
                var r = [], ri = -1;
                for (var i = 0, ci; ci = c[i]; i++) {
                    var cns = ci.childNodes, j = 0, cn, empty = true;
                    while (cn = cns[j]) {
                        ++j;
                        if (cn.nodeType == 1 || cn.nodeType == 3) {
                            empty = false;
                            break;
                        }
                    }
                    if (empty) {
                        r[++ri] = ci;
                    }
                }
                return r;
            },

            "contains": function (c, v) {
                var r = [], ri = -1;
                for (var i = 0, ci; ci = c[i]; i++) {
                    if ((ci.textContent || ci.innerText || '').indexOf(v) != -1) {
                        r[++ri] = ci;
                    }
                }
                return r;
            },

            "nodeValue": function (c, v) {
                var r = [], ri = -1;
                for (var i = 0, ci; ci = c[i]; i++) {
                    if (ci.firstChild && ci.firstChild.nodeValue == v) {
                        r[++ri] = ci;
                    }
                }
                return r;
            },

            "checked": function (c) {
                var r = [], ri = -1;
                for (var i = 0, ci; ci = c[i]; i++) {
                    if (ci.checked == true) {
                        r[++ri] = ci;
                    }
                }
                return r;
            },

            "not": function (c, ss) {
                return Ext.DomQuery.filter(c, ss, true);
            },

            "any": function (c, selectors) {
                var ss = selectors.split('|'),
                	r = [], ri = -1, s;
                for (var i = 0, ci; ci = c[i]; i++) {
                    for (var j = 0; s = ss[j]; j++) {
                        if (Ext.DomQuery.is(ci, s)) {
                            r[++ri] = ci;
                            break;
                        }
                    }
                }
                return r;
            },

            "odd": function (c) {
                return this["nth-child"](c, "odd");
            },

            "even": function (c) {
                return this["nth-child"](c, "even");
            },

            "nth": function (c, a) {
                return c[a - 1] || [];
            },

            "first": function (c) {
                return c[0] || [];
            },

            "last": function (c) {
                return c[c.length - 1] || [];
            },

            "has": function (c, ss) {
                var s = Ext.DomQuery.select,
                	r = [], ri = -1;
                for (var i = 0, ci; ci = c[i]; i++) {
                    if (s(ss, ci).length > 0) {
                        r[++ri] = ci;
                    }
                }
                return r;
            },

            "next": function (c, ss) {
                var is = Ext.DomQuery.is,
                	r = [], ri = -1;
                for (var i = 0, ci; ci = c[i]; i++) {
                    var n = next(ci);
                    if (n && is(n, ss)) {
                        r[++ri] = ci;
                    }
                }
                return r;
            },

            "prev": function (c, ss) {
                var is = Ext.DomQuery.is,
                	r = [], ri = -1;
                for (var i = 0, ci; ci = c[i]; i++) {
                    var n = prev(ci);
                    if (n && is(n, ss)) {
                        r[++ri] = ci;
                    }
                }
                return r;
            }
        }
    };
} ();


Ext.query = Ext.DomQuery.select;

Ext.util.DelayedTask = function (fn, scope, args) {
    var me = this,
    	id,
    	call = function () {
    	    clearInterval(id);
    	    id = null;
    	    fn.apply(scope, args || []);
    	};


    me.delay = function (delay, newFn, newScope, newArgs) {
        me.cancel();
        fn = newFn || fn;
        scope = newScope || scope;
        args = newArgs || args;
        id = setInterval(call, delay);
    };


    me.cancel = function () {
        if (id) {
            clearInterval(id);
            id = null;
        }
    };
};
(function () {
    var DOC = document;

    Ext.Element = function (element, forceNew) {
        var dom = typeof element == "string" ?
              DOC.getElementById(element) : element,
        id;

        if (!dom) return null;

        id = dom.id;

        if (!forceNew && id && Ext.elCache[id]) {
            return Ext.elCache[id].el;
        }


        this.dom = dom;


        this.id = id || Ext.id(dom);
    };

    var DH = Ext.DomHelper,
    El = Ext.Element,
    EC = Ext.elCache;

    El.prototype = {

        set: function (o, useSet) {
            var el = this.dom,
            attr,
            val,
            useSet = (useSet !== false) && !!el.setAttribute;

            for (attr in o) {
                if (o.hasOwnProperty(attr)) {
                    val = o[attr];
                    if (attr == 'style') {
                        DH.applyStyles(el, val);
                    } else if (attr == 'cls') {
                        el.className = val;
                    } else if (useSet) {
                        el.setAttribute(attr, val);
                    } else {
                        el[attr] = val;
                    }
                }
            }
            return this;
        },


















































        defaultUnit: "px",


        is: function (simpleSelector) {
            return Ext.DomQuery.is(this.dom, simpleSelector);
        },


        focus: function (defer, dom) {
            var me = this,
            dom = dom || me.dom;
            try {
                if (Number(defer)) {
                    me.focus.defer(defer, null, [null, dom]);
                } else {
                    dom.focus();
                }
            } catch (e) { }
            return me;
        },


        blur: function () {
            try {
                this.dom.blur();
            } catch (e) { }
            return this;
        },


        getValue: function (asNumber) {
            var val = this.dom.value;
            return asNumber ? parseInt(val, 10) : val;
        },


        addListener: function (eventName, fn, scope, options) {
            Ext.EventManager.on(this.dom, eventName, fn, scope || this, options);
            return this;
        },


        removeListener: function (eventName, fn, scope) {
            Ext.EventManager.removeListener(this.dom, eventName, fn, scope || this);
            return this;
        },


        removeAllListeners: function () {
            Ext.EventManager.removeAll(this.dom);
            return this;
        },


        purgeAllListeners: function () {
            Ext.EventManager.purgeElement(this, true);
            return this;
        },

        addUnits: function (size) {
            if (size === "" || size == "auto" || size === undefined) {
                size = size || '';
            } else if (!isNaN(size) || !unitPattern.test(size)) {
                size = size + (this.defaultUnit || 'px');
            }
            return size;
        },


        load: function (url, params, cb) {
            Ext.Ajax.request(Ext.apply({
                params: params,
                url: url.url || url,
                callback: cb,
                el: this.dom,
                indicatorText: url.indicatorText || ''
            }, Ext.isObject(url) ? url : {}));
            return this;
        },


        isBorderBox: function () {
            return Ext.isBorderBox || Ext.isForcedBorderBox || noBoxAdjust[(this.dom.tagName || "").toLowerCase()];
        },


        remove: function () {
            var me = this,
            dom = me.dom;

            if (dom) {
                delete me.dom;
                Ext.removeNode(dom);
            }
        },


        hover: function (overFn, outFn, scope, options) {
            var me = this;
            me.on('mouseenter', overFn, scope || me.dom, options);
            me.on('mouseleave', outFn, scope || me.dom, options);
            return me;
        },


        contains: function (el) {
            return !el ? false : Ext.lib.Dom.isAncestor(this.dom, el.dom ? el.dom : el);
        },


        getAttributeNS: function (ns, name) {
            return this.getAttribute(name, ns);
        },


        getAttribute: Ext.isIE ? function (name, ns) {
            var d = this.dom,
            type = typeof d[ns + ":" + name];

            if (['undefined', 'unknown'].indexOf(type) == -1) {
                return d[ns + ":" + name];
            }
            return d[name];
        } : function (name, ns) {
            var d = this.dom;
            return d.getAttributeNS(ns, name) || d.getAttribute(ns + ":" + name) || d.getAttribute(name) || d[name];
        },


        update: function (html) {
            if (this.dom) {
                this.dom.innerHTML = html;
            }
            return this;
        }
    };

    var ep = El.prototype;

    El.addMethods = function (o) {
        Ext.apply(ep, o);
    };


    ep.on = ep.addListener;


    ep.un = ep.removeListener;


    ep.autoBoxAdjust = true;


    var unitPattern = /\d+(px|em|%|en|ex|pt|in|cm|mm|pc)$/i,
    docEl;




    El.get = function (el) {
        var ex,
        elm,
        id;
        if (!el) { return null; }
        if (typeof el == "string") {
            if (!(elm = DOC.getElementById(el))) {
                return null;
            }
            if (EC[el] && EC[el].el) {
                ex = EC[el].el;
                ex.dom = elm;
            } else {
                ex = El.addToCache(new El(elm));
            }
            return ex;
        } else if (el.tagName) {
            if (!(id = el.id)) {
                id = Ext.id(el);
            }
            if (EC[id] && EC[id].el) {
                ex = EC[id].el;
                ex.dom = el;
            } else {
                ex = El.addToCache(new El(el));
            }
            return ex;
        } else if (el instanceof El) {
            if (el != docEl) {




                if (Ext.isIE && (el.id == undefined || el.id == '')) {
                    el.dom = el.dom;
                } else {
                    el.dom = DOC.getElementById(el.id) || el.dom;
                }
            }
            return el;
        } else if (el.isComposite) {
            return el;
        } else if (Ext.isArray(el)) {
            return El.select(el);
        } else if (el == DOC) {

            if (!docEl) {
                var f = function () { };
                f.prototype = El.prototype;
                docEl = new f();
                docEl.dom = DOC;
            }
            return docEl;
        }
        return null;
    };

    El.addToCache = function (el, id) {
        id = id || el.id;
        EC[id] = {
            el: el,
            data: {},
            events: {}
        };
        return el;
    };


    El.data = function (el, key, value) {
        el = El.get(el);
        if (!el) {
            return null;
        }
        var c = EC[el.id].data;
        if (arguments.length == 2) {
            return c[key];
        } else {
            return (c[key] = value);
        }
    };




    function garbageCollect() {
        if (!Ext.enableGarbageCollector) {
            clearInterval(El.collectorThreadId);
        } else {
            var eid,
            el,
            d,
            o;

            for (eid in EC) {
                o = EC[eid];
                if (o.skipGC) {
                    continue;
                }
                el = o.el;
                d = el.dom;

















                if (!d || !d.parentNode || (!d.offsetParent && !DOC.getElementById(eid))) {
                    if (Ext.enableListenerCollection) {
                        Ext.EventManager.removeAll(d);
                    }
                    delete EC[eid];
                }
            }

            if (Ext.isIE) {
                var t = {};
                for (eid in EC) {
                    t[eid] = EC[eid];
                }
                EC = Ext.elCache = t;
            }
        }
    }
    El.collectorThreadId = setInterval(garbageCollect, 30000);

    var flyFn = function () { };
    flyFn.prototype = El.prototype;


    El.Flyweight = function (dom) {
        this.dom = dom;
    };

    El.Flyweight.prototype = new flyFn();
    El.Flyweight.prototype.isFlyweight = true;
    El._flyweights = {};


    El.fly = function (el, named) {
        var ret = null;
        named = named || '_global';

        if (el = Ext.getDom(el)) {
            (El._flyweights[named] = El._flyweights[named] || new El.Flyweight()).dom = el;
            ret = El._flyweights[named];
        }
        return ret;
    };


    Ext.get = El.get;


    Ext.fly = El.fly;


    var noBoxAdjust = Ext.isStrict ? {
        select: 1
    } : {
        input: 1, select: 1, textarea: 1
    };
    if (Ext.isIE || Ext.isGecko) {
        noBoxAdjust['button'] = 1;
    }

})();

Ext.Element.addMethods(function () {
    var PARENTNODE = 'parentNode',
		NEXTSIBLING = 'nextSibling',
		PREVIOUSSIBLING = 'previousSibling',
		DQ = Ext.DomQuery,
		GET = Ext.get;

    return {

        findParent: function (simpleSelector, maxDepth, returnEl) {
            var p = this.dom,
	        	b = document.body,
	        	depth = 0,
	        	stopEl;
            if (Ext.isGecko && Object.prototype.toString.call(p) == '[object XULElement]') {
                return null;
            }
            maxDepth = maxDepth || 50;
            if (isNaN(maxDepth)) {
                stopEl = Ext.getDom(maxDepth);
                maxDepth = Number.MAX_VALUE;
            }
            while (p && p.nodeType == 1 && depth < maxDepth && p != b && p != stopEl) {
                if (DQ.is(p, simpleSelector)) {
                    return returnEl ? GET(p) : p;
                }
                depth++;
                p = p.parentNode;
            }
            return null;
        },


        findParentNode: function (simpleSelector, maxDepth, returnEl) {
            var p = Ext.fly(this.dom.parentNode, '_internal');
            return p ? p.findParent(simpleSelector, maxDepth, returnEl) : null;
        },


        up: function (simpleSelector, maxDepth) {
            return this.findParentNode(simpleSelector, maxDepth, true);
        },


        select: function (selector) {
            return Ext.Element.select(selector, this.dom);
        },


        query: function (selector) {
            return DQ.select(selector, this.dom);
        },


        child: function (selector, returnDom) {
            var n = DQ.selectNode(selector, this.dom);
            return returnDom ? n : GET(n);
        },


        down: function (selector, returnDom) {
            var n = DQ.selectNode(" > " + selector, this.dom);
            return returnDom ? n : GET(n);
        },


        parent: function (selector, returnDom) {
            return this.matchNode(PARENTNODE, PARENTNODE, selector, returnDom);
        },


        next: function (selector, returnDom) {
            return this.matchNode(NEXTSIBLING, NEXTSIBLING, selector, returnDom);
        },


        prev: function (selector, returnDom) {
            return this.matchNode(PREVIOUSSIBLING, PREVIOUSSIBLING, selector, returnDom);
        },



        first: function (selector, returnDom) {
            return this.matchNode(NEXTSIBLING, 'firstChild', selector, returnDom);
        },


        last: function (selector, returnDom) {
            return this.matchNode(PREVIOUSSIBLING, 'lastChild', selector, returnDom);
        },

        matchNode: function (dir, start, selector, returnDom) {
            var n = this.dom[start];
            while (n) {
                if (n.nodeType == 1 && (!selector || DQ.is(n, selector))) {
                    return !returnDom ? GET(n) : n;
                }
                n = n[dir];
            }
            return null;
        }
    };
} ());
Ext.Element.addMethods(
function () {
    var GETDOM = Ext.getDom,
		GET = Ext.get,
		DH = Ext.DomHelper;

    return {

        appendChild: function (el) {
            return GET(el).appendTo(this);
        },


        appendTo: function (el) {
            GETDOM(el).appendChild(this.dom);
            return this;
        },


        insertBefore: function (el) {
            (el = GETDOM(el)).parentNode.insertBefore(this.dom, el);
            return this;
        },


        insertAfter: function (el) {
            (el = GETDOM(el)).parentNode.insertBefore(this.dom, el.nextSibling);
            return this;
        },


        insertFirst: function (el, returnDom) {
            el = el || {};
            if (el.nodeType || el.dom || typeof el == 'string') {
                el = GETDOM(el);
                this.dom.insertBefore(el, this.dom.firstChild);
                return !returnDom ? GET(el) : el;
            } else {
                return this.createChild(el, this.dom.firstChild, returnDom);
            }
        },


        replace: function (el) {
            el = GET(el);
            this.insertBefore(el);
            el.remove();
            return this;
        },


        replaceWith: function (el) {
            var me = this;

            if (el.nodeType || el.dom || typeof el == 'string') {
                el = GETDOM(el);
                me.dom.parentNode.insertBefore(el, me.dom);
            } else {
                el = DH.insertBefore(me.dom, el);
            }

            delete Ext.elCache[me.id];
            Ext.removeNode(me.dom);
            me.id = Ext.id(me.dom = el);
            Ext.Element.addToCache(me.isFlyweight ? new Ext.Element(me.dom) : me);
            return me;
        },


        createChild: function (config, insertBefore, returnDom) {
            config = config || { tag: 'div' };
            return insertBefore ?
		    	   DH.insertBefore(insertBefore, config, returnDom !== true) :
		    	   DH[!this.dom.firstChild ? 'overwrite' : 'append'](this.dom, config, returnDom !== true);
        },


        wrap: function (config, returnDom) {
            var newEl = DH.insertBefore(this.dom, config || { tag: "div" }, !returnDom);
            newEl.dom ? newEl.dom.appendChild(this.dom) : newEl.appendChild(this.dom);
            return newEl;
        },


        insertHtml: function (where, html, returnEl) {
            var el = DH.insertHtml(where, this.dom, html);
            return returnEl ? Ext.get(el) : el;
        }
    };
} ());
Ext.Element.addMethods(function () {

    var supports = Ext.supports,
        propCache = {},
        camelRe = /(-[a-z])/gi,
        view = document.defaultView,
        opacityRe = /alpha\(opacity=(.*)\)/i,
        trimRe = /^\s+|\s+$/g,
        EL = Ext.Element,
        spacesRe = /\s+/,
        wordsRe = /\w/g,
        PADDING = "padding",
        MARGIN = "margin",
        BORDER = "border",
        LEFT = "-left",
        RIGHT = "-right",
        TOP = "-top",
        BOTTOM = "-bottom",
        WIDTH = "-width",
        MATH = Math,
        HIDDEN = 'hidden',
        ISCLIPPED = 'isClipped',
        OVERFLOW = 'overflow',
        OVERFLOWX = 'overflow-x',
        OVERFLOWY = 'overflow-y',
        ORIGINALCLIP = 'originalClip',

        borders = { l: BORDER + LEFT + WIDTH, r: BORDER + RIGHT + WIDTH, t: BORDER + TOP + WIDTH, b: BORDER + BOTTOM + WIDTH },
        paddings = { l: PADDING + LEFT, r: PADDING + RIGHT, t: PADDING + TOP, b: PADDING + BOTTOM },
        margins = { l: MARGIN + LEFT, r: MARGIN + RIGHT, t: MARGIN + TOP, b: MARGIN + BOTTOM },
        data = Ext.Element.data;



    function camelFn(m, a) {
        return a.charAt(1).toUpperCase();
    }

    function chkCache(prop) {
        return propCache[prop] || (propCache[prop] = prop == 'float' ? (supports.cssFloat ? 'cssFloat' : 'styleFloat') : prop.replace(camelRe, camelFn));
    }

    return {

        adjustWidth: function (width) {
            var me = this;
            var isNum = (typeof width == "number");
            if (isNum && me.autoBoxAdjust && !me.isBorderBox()) {
                width -= (me.getBorderWidth("lr") + me.getPadding("lr"));
            }
            return (isNum && width < 0) ? 0 : width;
        },


        adjustHeight: function (height) {
            var me = this;
            var isNum = (typeof height == "number");
            if (isNum && me.autoBoxAdjust && !me.isBorderBox()) {
                height -= (me.getBorderWidth("tb") + me.getPadding("tb"));
            }
            return (isNum && height < 0) ? 0 : height;
        },



        addClass: function (className) {
            var me = this,
                i,
                len,
                v,
                cls = [];

            if (!Ext.isArray(className)) {
                if (typeof className == 'string' && !this.hasClass(className)) {
                    me.dom.className += " " + className;
                }
            }
            else {
                for (i = 0, len = className.length; i < len; i++) {
                    v = className[i];
                    if (typeof v == 'string' && (' ' + me.dom.className + ' ').indexOf(' ' + v + ' ') == -1) {
                        cls.push(v);
                    }
                }
                if (cls.length) {
                    me.dom.className += " " + cls.join(" ");
                }
            }
            return me;
        },


        removeClass: function (className) {
            var me = this,
                i,
                idx,
                len,
                cls,
                elClasses;
            if (!Ext.isArray(className)) {
                className = [className];
            }
            if (me.dom && me.dom.className) {
                elClasses = me.dom.className.replace(trimRe, '').split(spacesRe);
                for (i = 0, len = className.length; i < len; i++) {
                    cls = className[i];
                    if (typeof cls == 'string') {
                        cls = cls.replace(trimRe, '');
                        idx = elClasses.indexOf(cls);
                        if (idx != -1) {
                            elClasses.splice(idx, 1);
                        }
                    }
                }
                me.dom.className = elClasses.join(" ");
            }
            return me;
        },


        radioClass: function (className) {
            var cn = this.dom.parentNode.childNodes,
                v,
                i,
                len;
            className = Ext.isArray(className) ? className : [className];
            for (i = 0, len = cn.length; i < len; i++) {
                v = cn[i];
                if (v && v.nodeType == 1) {
                    Ext.fly(v, '_internal').removeClass(className);
                }
            };
            return this.addClass(className);
        },


        toggleClass: function (className) {
            return this.hasClass(className) ? this.removeClass(className) : this.addClass(className);
        },


        hasClass: function (className) {
            return className && (' ' + this.dom.className + ' ').indexOf(' ' + className + ' ') != -1;
        },


        replaceClass: function (oldClassName, newClassName) {
            return this.removeClass(oldClassName).addClass(newClassName);
        },

        isStyle: function (style, val) {
            return this.getStyle(style) == val;
        },


        getStyle: function () {
            return view && view.getComputedStyle ?
                function (prop) {
                    var el = this.dom,
                        v,
                        cs,
                        out,
                        display;

                    if (el == document) {
                        return null;
                    }
                    prop = chkCache(prop);
                    out = (v = el.style[prop]) ? v :
                           (cs = view.getComputedStyle(el, "")) ? cs[prop] : null;



                    if (prop == 'marginRight' && out != '0px' && !supports.correctRightMargin) {
                        display = el.style.display;
                        el.style.display = 'inline-block';
                        out = view.getComputedStyle(el, '').marginRight;
                        el.style.display = display;
                    }

                    if (prop == 'backgroundColor' && out == 'rgba(0, 0, 0, 0)' && !supports.correctTransparentColor) {
                        out = 'transparent';
                    }
                    return out;
                } :
                function (prop) {
                    var el = this.dom,
                        m,
                        cs;

                    if (el == document) return null;
                    if (prop == 'opacity') {
                        if (el.style.filter.match) {
                            if (m = el.style.filter.match(opacityRe)) {
                                var fv = parseFloat(m[1]);
                                if (!isNaN(fv)) {
                                    return fv ? fv / 100 : 0;
                                }
                            }
                        }
                        return 1;
                    }
                    prop = chkCache(prop);
                    return el.style[prop] || ((cs = el.currentStyle) ? cs[prop] : null);
                };
        } (),


        getColor: function (attr, defaultValue, prefix) {
            var v = this.getStyle(attr),
                color = (typeof prefix != 'undefined') ? prefix : '#',
                h;

            if (!v || (/transparent|inherit/.test(v))) {
                return defaultValue;
            }
            if (/^r/.test(v)) {
                Ext.each(v.slice(4, v.length - 1).split(','), function (s) {
                    h = parseInt(s, 10);
                    color += (h < 16 ? '0' : '') + h.toString(16);
                });
            } else {
                v = v.replace('#', '');
                color += v.length == 3 ? v.replace(/^(\w)(\w)(\w)$/, '$1$1$2$2$3$3') : v;
            }
            return (color.length > 5 ? color.toLowerCase() : defaultValue);
        },


        setStyle: function (prop, value) {
            var tmp, style;

            if (typeof prop != 'object') {
                tmp = {};
                tmp[prop] = value;
                prop = tmp;
            }
            for (style in prop) {
                value = prop[style];
                style == 'opacity' ?
                    this.setOpacity(value) :
                    this.dom.style[chkCache(style)] = value;
            }
            return this;
        },


        setOpacity: function (opacity, animate) {
            var me = this,
                s = me.dom.style;

            if (!animate || !me.anim) {
                if (Ext.isIE) {
                    var opac = opacity < 1 ? 'alpha(opacity=' + opacity * 100 + ')' : '',
                    val = s.filter.replace(opacityRe, '').replace(trimRe, '');

                    s.zoom = 1;
                    s.filter = val + (val.length > 0 ? ' ' : '') + opac;
                } else {
                    s.opacity = opacity;
                }
            } else {
                me.anim({ opacity: { to: opacity} }, me.preanim(arguments, 1), null, .35, 'easeIn');
            }
            return me;
        },


        clearOpacity: function () {
            var style = this.dom.style;
            if (Ext.isIE) {
                if (!Ext.isEmpty(style.filter)) {
                    style.filter = style.filter.replace(opacityRe, '').replace(trimRe, '');
                }
            } else {
                style.opacity = style['-moz-opacity'] = style['-khtml-opacity'] = '';
            }
            return this;
        },


        getHeight: function (contentHeight) {
            var me = this,
                dom = me.dom,
                hidden = Ext.isIE && me.isStyle('display', 'none'),
                h = MATH.max(dom.offsetHeight, hidden ? 0 : dom.clientHeight) || 0;

            h = !contentHeight ? h : h - me.getBorderWidth("tb") - me.getPadding("tb");
            return h < 0 ? 0 : h;
        },


        getWidth: function (contentWidth) {
            var me = this,
                dom = me.dom,
                hidden = Ext.isIE && me.isStyle('display', 'none'),
                w = MATH.max(dom.offsetWidth, hidden ? 0 : dom.clientWidth) || 0;
            w = !contentWidth ? w : w - me.getBorderWidth("lr") - me.getPadding("lr");
            return w < 0 ? 0 : w;
        },


        setWidth: function (width, animate) {
            var me = this;
            width = me.adjustWidth(width);
            !animate || !me.anim ?
                me.dom.style.width = me.addUnits(width) :
                me.anim({ width: { to: width} }, me.preanim(arguments, 1));
            return me;
        },


        setHeight: function (height, animate) {
            var me = this;
            height = me.adjustHeight(height);
            !animate || !me.anim ?
                me.dom.style.height = me.addUnits(height) :
                me.anim({ height: { to: height} }, me.preanim(arguments, 1));
            return me;
        },


        getBorderWidth: function (side) {
            return this.addStyles(side, borders);
        },


        getPadding: function (side) {
            return this.addStyles(side, paddings);
        },


        clip: function () {
            var me = this,
                dom = me.dom;

            if (!data(dom, ISCLIPPED)) {
                data(dom, ISCLIPPED, true);
                data(dom, ORIGINALCLIP, {
                    o: me.getStyle(OVERFLOW),
                    x: me.getStyle(OVERFLOWX),
                    y: me.getStyle(OVERFLOWY)
                });
                me.setStyle(OVERFLOW, HIDDEN);
                me.setStyle(OVERFLOWX, HIDDEN);
                me.setStyle(OVERFLOWY, HIDDEN);
            }
            return me;
        },


        unclip: function () {
            var me = this,
                dom = me.dom;

            if (data(dom, ISCLIPPED)) {
                data(dom, ISCLIPPED, false);
                var o = data(dom, ORIGINALCLIP);
                if (o.o) {
                    me.setStyle(OVERFLOW, o.o);
                }
                if (o.x) {
                    me.setStyle(OVERFLOWX, o.x);
                }
                if (o.y) {
                    me.setStyle(OVERFLOWY, o.y);
                }
            }
            return me;
        },


        addStyles: function (sides, styles) {
            var ttlSize = 0,
                sidesArr = sides.match(wordsRe),
                side,
                size,
                i,
                len = sidesArr.length;
            for (i = 0; i < len; i++) {
                side = sidesArr[i];
                size = side && parseInt(this.getStyle(styles[side]), 10);
                if (size) {
                    ttlSize += MATH.abs(size);
                }
            }
            return ttlSize;
        },

        margins: margins
    };
} ()
);

(function () {
    var D = Ext.lib.Dom,
        LEFT = "left",
        RIGHT = "right",
        TOP = "top",
        BOTTOM = "bottom",
        POSITION = "position",
        STATIC = "static",
        RELATIVE = "relative",
        AUTO = "auto",
        ZINDEX = "z-index";

    Ext.Element.addMethods({

        getX: function () {
            return D.getX(this.dom);
        },


        getY: function () {
            return D.getY(this.dom);
        },


        getXY: function () {
            return D.getXY(this.dom);
        },


        getOffsetsTo: function (el) {
            var o = this.getXY(),
        	e = Ext.fly(el, '_internal').getXY();
            return [o[0] - e[0], o[1] - e[1]];
        },


        setX: function (x, animate) {
            return this.setXY([x, this.getY()], this.animTest(arguments, animate, 1));
        },


        setY: function (y, animate) {
            return this.setXY([this.getX(), y], this.animTest(arguments, animate, 1));
        },


        setLeft: function (left) {
            this.setStyle(LEFT, this.addUnits(left));
            return this;
        },


        setTop: function (top) {
            this.setStyle(TOP, this.addUnits(top));
            return this;
        },


        setRight: function (right) {
            this.setStyle(RIGHT, this.addUnits(right));
            return this;
        },


        setBottom: function (bottom) {
            this.setStyle(BOTTOM, this.addUnits(bottom));
            return this;
        },


        setXY: function (pos, animate) {
            var me = this;
            if (!animate || !me.anim) {
                D.setXY(me.dom, pos);
            } else {
                me.anim({ points: { to: pos} }, me.preanim(arguments, 1), 'motion');
            }
            return me;
        },


        setLocation: function (x, y, animate) {
            return this.setXY([x, y], this.animTest(arguments, animate, 2));
        },


        moveTo: function (x, y, animate) {
            return this.setXY([x, y], this.animTest(arguments, animate, 2));
        },


        getLeft: function (local) {
            return !local ? this.getX() : parseInt(this.getStyle(LEFT), 10) || 0;
        },


        getRight: function (local) {
            var me = this;
            return !local ? me.getX() + me.getWidth() : (me.getLeft(true) + me.getWidth()) || 0;
        },


        getTop: function (local) {
            return !local ? this.getY() : parseInt(this.getStyle(TOP), 10) || 0;
        },


        getBottom: function (local) {
            var me = this;
            return !local ? me.getY() + me.getHeight() : (me.getTop(true) + me.getHeight()) || 0;
        },


        position: function (pos, zIndex, x, y) {
            var me = this;

            if (!pos && me.isStyle(POSITION, STATIC)) {
                me.setStyle(POSITION, RELATIVE);
            } else if (pos) {
                me.setStyle(POSITION, pos);
            }
            if (zIndex) {
                me.setStyle(ZINDEX, zIndex);
            }
            if (x || y) me.setXY([x || false, y || false]);
        },


        clearPositioning: function (value) {
            value = value || '';
            this.setStyle({
                left: value,
                right: value,
                top: value,
                bottom: value,
                "z-index": "",
                position: STATIC
            });
            return this;
        },


        getPositioning: function () {
            var l = this.getStyle(LEFT);
            var t = this.getStyle(TOP);
            return {
                "position": this.getStyle(POSITION),
                "left": l,
                "right": l ? "" : this.getStyle(RIGHT),
                "top": t,
                "bottom": t ? "" : this.getStyle(BOTTOM),
                "z-index": this.getStyle(ZINDEX)
            };
        },


        setPositioning: function (pc) {
            var me = this,
	    	style = me.dom.style;

            me.setStyle(pc);

            if (pc.right == AUTO) {
                style.right = "";
            }
            if (pc.bottom == AUTO) {
                style.bottom = "";
            }

            return me;
        },


        translatePoints: function (x, y) {
            y = isNaN(x[1]) ? y : x[1];
            x = isNaN(x[0]) ? x : x[0];
            var me = this,
        	relative = me.isStyle(POSITION, RELATIVE),
        	o = me.getXY(),
        	l = parseInt(me.getStyle(LEFT), 10),
        	t = parseInt(me.getStyle(TOP), 10);

            l = !isNaN(l) ? l : (relative ? 0 : me.dom.offsetLeft);
            t = !isNaN(t) ? t : (relative ? 0 : me.dom.offsetTop);

            return { left: (x - o[0] + l), top: (y - o[1] + t) };
        },

        animTest: function (args, animate, i) {
            return !!animate && this.preanim ? this.preanim(args, i) : false;
        }
    });
})();
Ext.Element.addMethods({

    isScrollable: function () {
        var dom = this.dom;
        return dom.scrollHeight > dom.clientHeight || dom.scrollWidth > dom.clientWidth;
    },


    scrollTo: function (side, value) {
        this.dom["scroll" + (/top/i.test(side) ? "Top" : "Left")] = value;
        return this;
    },


    getScroll: function () {
        var d = this.dom,
            doc = document,
            body = doc.body,
            docElement = doc.documentElement,
            l,
            t,
            ret;

        if (d == doc || d == body) {
            if (Ext.isIE && Ext.isStrict) {
                l = docElement.scrollLeft;
                t = docElement.scrollTop;
            } else {
                l = window.pageXOffset;
                t = window.pageYOffset;
            }
            ret = { left: l || (body ? body.scrollLeft : 0), top: t || (body ? body.scrollTop : 0) };
        } else {
            ret = { left: d.scrollLeft, top: d.scrollTop };
        }
        return ret;
    }
});

Ext.Element.VISIBILITY = 1;

Ext.Element.DISPLAY = 2;


Ext.Element.OFFSETS = 3;


Ext.Element.ASCLASS = 4;


Ext.Element.visibilityCls = 'x-hide-nosize';

Ext.Element.addMethods(function () {
    var El = Ext.Element,
        OPACITY = "opacity",
        VISIBILITY = "visibility",
        DISPLAY = "display",
        HIDDEN = "hidden",
        OFFSETS = "offsets",
        ASCLASS = "asclass",
        NONE = "none",
        NOSIZE = 'nosize',
        ORIGINALDISPLAY = 'originalDisplay',
        VISMODE = 'visibilityMode',
        ISVISIBLE = 'isVisible',
        data = El.data,
        getDisplay = function (dom) {
            var d = data(dom, ORIGINALDISPLAY);
            if (d === undefined) {
                data(dom, ORIGINALDISPLAY, d = '');
            }
            return d;
        },
        getVisMode = function (dom) {
            var m = data(dom, VISMODE);
            if (m === undefined) {
                data(dom, VISMODE, m = 1);
            }
            return m;
        };

    return {

        originalDisplay: "",
        visibilityMode: 1,


        setVisibilityMode: function (visMode) {
            data(this.dom, VISMODE, visMode);
            return this;
        },


        animate: function (args, duration, onComplete, easing, animType) {
            this.anim(args, { duration: duration, callback: onComplete, easing: easing }, animType);
            return this;
        },


        anim: function (args, opt, animType, defaultDur, defaultEase, cb) {
            animType = animType || 'run';
            opt = opt || {};
            var me = this,
                anim = Ext.lib.Anim[animType](
                    me.dom,
                    args,
                    (opt.duration || defaultDur) || .35,
                    (opt.easing || defaultEase) || 'easeOut',
                    function () {
                        if (cb) cb.call(me);
                        if (opt.callback) opt.callback.call(opt.scope || me, me, opt);
                    },
                    me
                );
            opt.anim = anim;
            return anim;
        },


        preanim: function (a, i) {
            return !a[i] ? false : (typeof a[i] == 'object' ? a[i] : { duration: a[i + 1], callback: a[i + 2], easing: a[i + 3] });
        },


        isVisible: function () {
            var me = this,
                dom = me.dom,
                visible = data(dom, ISVISIBLE);

            if (typeof visible == 'boolean') {
                return visible;
            }

            visible = !me.isStyle(VISIBILITY, HIDDEN) &&
                      !me.isStyle(DISPLAY, NONE) &&
                      !((getVisMode(dom) == El.ASCLASS) && me.hasClass(me.visibilityCls || El.visibilityCls));

            data(dom, ISVISIBLE, visible);
            return visible;
        },


        setVisible: function (visible, animate) {
            var me = this, isDisplay, isVisibility, isOffsets, isNosize,
                dom = me.dom,
                visMode = getVisMode(dom);



            if (typeof animate == 'string') {
                switch (animate) {
                    case DISPLAY:
                        visMode = El.DISPLAY;
                        break;
                    case VISIBILITY:
                        visMode = El.VISIBILITY;
                        break;
                    case OFFSETS:
                        visMode = El.OFFSETS;
                        break;
                    case NOSIZE:
                    case ASCLASS:
                        visMode = El.ASCLASS;
                        break;
                }
                me.setVisibilityMode(visMode);
                animate = false;
            }

            if (!animate || !me.anim) {
                if (visMode == El.ASCLASS) {

                    me[visible ? 'removeClass' : 'addClass'](me.visibilityCls || El.visibilityCls);

                } else if (visMode == El.DISPLAY) {

                    return me.setDisplayed(visible);

                } else if (visMode == El.OFFSETS) {

                    if (!visible) {
                        me.hideModeStyles = {
                            position: me.getStyle('position'),
                            top: me.getStyle('top'),
                            left: me.getStyle('left')
                        };
                        me.applyStyles({ position: 'absolute', top: '-10000px', left: '-10000px' });
                    } else {
                        me.applyStyles(me.hideModeStyles || { position: '', top: '', left: '' });
                        delete me.hideModeStyles;
                    }

                } else {
                    me.fixDisplay();
                    dom.style.visibility = visible ? "visible" : HIDDEN;
                }
            } else {

                if (visible) {
                    me.setOpacity(.01);
                    me.setVisible(true);
                }
                me.anim({ opacity: { to: (visible ? 1 : 0)} },
                        me.preanim(arguments, 1),
                        null,
                        .35,
                        'easeIn',
                        function () {
                            visible || me.setVisible(false).setOpacity(1);
                        });
            }
            data(dom, ISVISIBLE, visible);
            return me;
        },



        hasMetrics: function () {
            var dom = this.dom;
            return this.isVisible() || (getVisMode(dom) == El.VISIBILITY);
        },


        toggle: function (animate) {
            var me = this;
            me.setVisible(!me.isVisible(), me.preanim(arguments, 0));
            return me;
        },


        setDisplayed: function (value) {
            if (typeof value == "boolean") {
                value = value ? getDisplay(this.dom) : NONE;
            }
            this.setStyle(DISPLAY, value);
            return this;
        },


        fixDisplay: function () {
            var me = this;
            if (me.isStyle(DISPLAY, NONE)) {
                me.setStyle(VISIBILITY, HIDDEN);
                me.setStyle(DISPLAY, getDisplay(this.dom));
                if (me.isStyle(DISPLAY, NONE)) {
                    me.setStyle(DISPLAY, "block");
                }
            }
        },


        hide: function (animate) {

            if (typeof animate == 'string') {
                this.setVisible(false, animate);
                return this;
            }
            this.setVisible(false, this.preanim(arguments, 0));
            return this;
        },


        show: function (animate) {

            if (typeof animate == 'string') {
                this.setVisible(true, animate);
                return this;
            }
            this.setVisible(true, this.preanim(arguments, 0));
            return this;
        }
    };
} ()); (function () {

    var NULL = null,
        UNDEFINED = undefined,
        TRUE = true,
        FALSE = false,
        SETX = "setX",
        SETY = "setY",
        SETXY = "setXY",
        LEFT = "left",
        BOTTOM = "bottom",
        TOP = "top",
        RIGHT = "right",
        HEIGHT = "height",
        WIDTH = "width",
        POINTS = "points",
        HIDDEN = "hidden",
        ABSOLUTE = "absolute",
        VISIBLE = "visible",
        MOTION = "motion",
        POSITION = "position",
        EASEOUT = "easeOut",

        flyEl = new Ext.Element.Flyweight(),
        queues = {},
        getObject = function (o) {
            return o || {};
        },
        fly = function (dom) {
            flyEl.dom = dom;
            flyEl.id = Ext.id(dom);
            return flyEl;
        },

        getQueue = function (id) {
            if (!queues[id]) {
                queues[id] = [];
            }
            return queues[id];
        },
        setQueue = function (id, value) {
            queues[id] = value;
        };


    Ext.enableFx = TRUE;


    Ext.Fx = {



        switchStatements: function (key, fn, argHash) {
            return fn.apply(this, argHash[key]);
        },


        slideIn: function (anchor, o) {
            o = getObject(o);
            var me = this,
            dom = me.dom,
            st = dom.style,
            xy,
            r,
            b,
            wrap,
            after,
            st,
            args,
            pt,
            bw,
            bh;

            anchor = anchor || "t";

            me.queueFx(o, function () {
                xy = fly(dom).getXY();

                fly(dom).fixDisplay();


                r = fly(dom).getFxRestore();
                b = { x: xy[0], y: xy[1], 0: xy[0], 1: xy[1], width: dom.offsetWidth, height: dom.offsetHeight };
                b.right = b.x + b.width;
                b.bottom = b.y + b.height;


                fly(dom).setWidth(b.width).setHeight(b.height);


                wrap = fly(dom).fxWrap(r.pos, o, HIDDEN);

                st.visibility = VISIBLE;
                st.position = ABSOLUTE;


                function after() {
                    fly(dom).fxUnwrap(wrap, r.pos, o);
                    st.width = r.width;
                    st.height = r.height;
                    fly(dom).afterFx(o);
                }


                pt = { to: [b.x, b.y] };
                bw = { to: b.width };
                bh = { to: b.height };

                function argCalc(wrap, style, ww, wh, sXY, sXYval, s1, s2, w, h, p) {
                    var ret = {};
                    fly(wrap).setWidth(ww).setHeight(wh);
                    if (fly(wrap)[sXY]) {
                        fly(wrap)[sXY](sXYval);
                    }
                    style[s1] = style[s2] = "0";
                    if (w) {
                        ret.width = w;
                    }
                    if (h) {
                        ret.height = h;
                    }
                    if (p) {
                        ret.points = p;
                    }
                    return ret;
                };

                args = fly(dom).switchStatements(anchor.toLowerCase(), argCalc, {
                    t: [wrap, st, b.width, 0, NULL, NULL, LEFT, BOTTOM, NULL, bh, NULL],
                    l: [wrap, st, 0, b.height, NULL, NULL, RIGHT, TOP, bw, NULL, NULL],
                    r: [wrap, st, b.width, b.height, SETX, b.right, LEFT, TOP, NULL, NULL, pt],
                    b: [wrap, st, b.width, b.height, SETY, b.bottom, LEFT, TOP, NULL, bh, pt],
                    tl: [wrap, st, 0, 0, NULL, NULL, RIGHT, BOTTOM, bw, bh, pt],
                    bl: [wrap, st, 0, 0, SETY, b.y + b.height, RIGHT, TOP, bw, bh, pt],
                    br: [wrap, st, 0, 0, SETXY, [b.right, b.bottom], LEFT, TOP, bw, bh, pt],
                    tr: [wrap, st, 0, 0, SETX, b.x + b.width, LEFT, BOTTOM, bw, bh, pt]
                });

                st.visibility = VISIBLE;
                fly(wrap).show();

                arguments.callee.anim = fly(wrap).fxanim(args,
                o,
                MOTION,
                .5,
                EASEOUT,
                after);
            });
            return me;
        },


        slideOut: function (anchor, o) {
            o = getObject(o);
            var me = this,
            dom = me.dom,
            st = dom.style,
            xy = me.getXY(),
            wrap,
            r,
            b,
            a,
            zero = { to: 0 };

            anchor = anchor || "t";

            me.queueFx(o, function () {


                r = fly(dom).getFxRestore();
                b = { x: xy[0], y: xy[1], 0: xy[0], 1: xy[1], width: dom.offsetWidth, height: dom.offsetHeight };
                b.right = b.x + b.width;
                b.bottom = b.y + b.height;


                fly(dom).setWidth(b.width).setHeight(b.height);


                wrap = fly(dom).fxWrap(r.pos, o, VISIBLE);

                st.visibility = VISIBLE;
                st.position = ABSOLUTE;
                fly(wrap).setWidth(b.width).setHeight(b.height);

                function after() {
                    o.useDisplay ? fly(dom).setDisplayed(FALSE) : fly(dom).hide();
                    fly(dom).fxUnwrap(wrap, r.pos, o);
                    st.width = r.width;
                    st.height = r.height;
                    fly(dom).afterFx(o);
                }

                function argCalc(style, s1, s2, p1, v1, p2, v2, p3, v3) {
                    var ret = {};

                    style[s1] = style[s2] = "0";
                    ret[p1] = v1;
                    if (p2) {
                        ret[p2] = v2;
                    }
                    if (p3) {
                        ret[p3] = v3;
                    }

                    return ret;
                };

                a = fly(dom).switchStatements(anchor.toLowerCase(), argCalc, {
                    t: [st, LEFT, BOTTOM, HEIGHT, zero],
                    l: [st, RIGHT, TOP, WIDTH, zero],
                    r: [st, LEFT, TOP, WIDTH, zero, POINTS, { to: [b.right, b.y]}],
                    b: [st, LEFT, TOP, HEIGHT, zero, POINTS, { to: [b.x, b.bottom]}],
                    tl: [st, RIGHT, BOTTOM, WIDTH, zero, HEIGHT, zero],
                    bl: [st, RIGHT, TOP, WIDTH, zero, HEIGHT, zero, POINTS, { to: [b.x, b.bottom]}],
                    br: [st, LEFT, TOP, WIDTH, zero, HEIGHT, zero, POINTS, { to: [b.x + b.width, b.bottom]}],
                    tr: [st, LEFT, BOTTOM, WIDTH, zero, HEIGHT, zero, POINTS, { to: [b.right, b.y]}]
                });

                arguments.callee.anim = fly(wrap).fxanim(a,
                o,
                MOTION,
                .5,
                EASEOUT,
                after);
            });
            return me;
        },


        puff: function (o) {
            o = getObject(o);
            var me = this,
            dom = me.dom,
            st = dom.style,
            width,
            height,
            r;

            me.queueFx(o, function () {
                width = fly(dom).getWidth();
                height = fly(dom).getHeight();
                fly(dom).clearOpacity();
                fly(dom).show();


                r = fly(dom).getFxRestore();

                function after() {
                    o.useDisplay ? fly(dom).setDisplayed(FALSE) : fly(dom).hide();
                    fly(dom).clearOpacity();
                    fly(dom).setPositioning(r.pos);
                    st.width = r.width;
                    st.height = r.height;
                    st.fontSize = '';
                    fly(dom).afterFx(o);
                }

                arguments.callee.anim = fly(dom).fxanim({
                    width: { to: fly(dom).adjustWidth(width * 2) },
                    height: { to: fly(dom).adjustHeight(height * 2) },
                    points: { by: [-width * .5, -height * .5] },
                    opacity: { to: 0 },
                    fontSize: { to: 200, unit: "%" }
                },
                o,
                MOTION,
                .5,
                EASEOUT,
                 after);
            });
            return me;
        },


        switchOff: function (o) {
            o = getObject(o);
            var me = this,
            dom = me.dom,
            st = dom.style,
            r;

            me.queueFx(o, function () {
                fly(dom).clearOpacity();
                fly(dom).clip();


                r = fly(dom).getFxRestore();

                function after() {
                    o.useDisplay ? fly(dom).setDisplayed(FALSE) : fly(dom).hide();
                    fly(dom).clearOpacity();
                    fly(dom).setPositioning(r.pos);
                    st.width = r.width;
                    st.height = r.height;
                    fly(dom).afterFx(o);
                };

                fly(dom).fxanim({ opacity: { to: 0.3} },
                NULL,
                NULL,
                .1,
                NULL,
                function () {
                    fly(dom).clearOpacity();
                    (function () {
                        fly(dom).fxanim({
                            height: { to: 1 },
                            points: { by: [0, fly(dom).getHeight() * .5] }
                        },
                            o,
                            MOTION,
                            0.3,
                            'easeIn',
                            after);
                    }).defer(100);
                });
            });
            return me;
        },


        highlight: function (color, o) {
            o = getObject(o);
            var me = this,
            dom = me.dom,
            attr = o.attr || "backgroundColor",
            a = {},
            restore;

            me.queueFx(o, function () {
                fly(dom).clearOpacity();
                fly(dom).show();

                function after() {
                    dom.style[attr] = restore;
                    fly(dom).afterFx(o);
                }
                restore = dom.style[attr];
                a[attr] = { from: color || "ffff9c", to: o.endColor || fly(dom).getColor(attr) || "ffffff" };
                arguments.callee.anim = fly(dom).fxanim(a,
                o,
                'color',
                1,
                'easeIn',
                after);
            });
            return me;
        },


        frame: function (color, count, o) {
            o = getObject(o);
            var me = this,
            dom = me.dom,
            proxy,
            active;

            me.queueFx(o, function () {
                color = color || '#C3DAF9';
                if (color.length == 6) {
                    color = '#' + color;
                }
                count = count || 1;
                fly(dom).show();

                var xy = fly(dom).getXY(),
                b = { x: xy[0], y: xy[1], 0: xy[0], 1: xy[1], width: dom.offsetWidth, height: dom.offsetHeight },
                queue = function () {
                    proxy = fly(document.body || document.documentElement).createChild({
                        style: {
                            position: ABSOLUTE,
                            'z-index': 35000,
                            border: '0px solid ' + color
                        }
                    });
                    return proxy.queueFx({}, animFn);
                };


                arguments.callee.anim = {
                    isAnimated: true,
                    stop: function () {
                        count = 0;
                        proxy.stopFx();
                    }
                };

                function animFn() {
                    var scale = Ext.isBorderBox ? 2 : 1;
                    active = proxy.anim({
                        top: { from: b.y, to: b.y - 20 },
                        left: { from: b.x, to: b.x - 20 },
                        borderWidth: { from: 0, to: 10 },
                        opacity: { from: 1, to: 0 },
                        height: { from: b.height, to: b.height + 20 * scale },
                        width: { from: b.width, to: b.width + 20 * scale }
                    }, {
                        duration: o.duration || 1,
                        callback: function () {
                            proxy.remove();
                            --count > 0 ? queue() : fly(dom).afterFx(o);
                        }
                    });
                    arguments.callee.anim = {
                        isAnimated: true,
                        stop: function () {
                            active.stop();
                        }
                    };
                };
                queue();
            });
            return me;
        },


        pause: function (seconds) {
            var dom = this.dom,
            t;

            this.queueFx({}, function () {
                t = setTimeout(function () {
                    fly(dom).afterFx({});
                }, seconds * 1000);
                arguments.callee.anim = {
                    isAnimated: true,
                    stop: function () {
                        clearTimeout(t);
                        fly(dom).afterFx({});
                    }
                };
            });
            return this;
        },


        fadeIn: function (o) {
            o = getObject(o);
            var me = this,
            dom = me.dom,
            to = o.endOpacity || 1;

            me.queueFx(o, function () {
                fly(dom).setOpacity(0);
                fly(dom).fixDisplay();
                dom.style.visibility = VISIBLE;
                arguments.callee.anim = fly(dom).fxanim({ opacity: { to: to} },
                o, NULL, .5, EASEOUT, function () {
                    if (to == 1) {
                        fly(dom).clearOpacity();
                    }
                    fly(dom).afterFx(o);
                });
            });
            return me;
        },


        fadeOut: function (o) {
            o = getObject(o);
            var me = this,
            dom = me.dom,
            style = dom.style,
            to = o.endOpacity || 0;

            me.queueFx(o, function () {
                arguments.callee.anim = fly(dom).fxanim({
                    opacity: { to: to}
                },
                o,
                NULL,
                .5,
                EASEOUT,
                function () {
                    if (to == 0) {
                        Ext.Element.data(dom, 'visibilityMode') == Ext.Element.DISPLAY || o.useDisplay ?
                            style.display = "none" :
                            style.visibility = HIDDEN;

                        fly(dom).clearOpacity();
                    }
                    fly(dom).afterFx(o);
                });
            });
            return me;
        },


        scale: function (w, h, o) {
            this.shift(Ext.apply({}, o, {
                width: w,
                height: h
            }));
            return this;
        },


        shift: function (o) {
            o = getObject(o);
            var dom = this.dom,
            a = {};

            this.queueFx(o, function () {
                for (var prop in o) {
                    if (o[prop] != UNDEFINED) {
                        a[prop] = { to: o[prop] };
                    }
                }

                a.width ? a.width.to = fly(dom).adjustWidth(o.width) : a;
                a.height ? a.height.to = fly(dom).adjustWidth(o.height) : a;

                if (a.x || a.y || a.xy) {
                    a.points = a.xy ||
                           { to: [a.x ? a.x.to : fly(dom).getX(),
                                   a.y ? a.y.to : fly(dom).getY()]
                           };
                }

                arguments.callee.anim = fly(dom).fxanim(a,
                o,
                MOTION,
                .35,
                EASEOUT,
                function () {
                    fly(dom).afterFx(o);
                });
            });
            return this;
        },


        ghost: function (anchor, o) {
            o = getObject(o);
            var me = this,
            dom = me.dom,
            st = dom.style,
            a = { opacity: { to: 0 }, points: {} },
            pt = a.points,
            r,
            w,
            h;

            anchor = anchor || "b";

            me.queueFx(o, function () {

                r = fly(dom).getFxRestore();
                w = fly(dom).getWidth();
                h = fly(dom).getHeight();

                function after() {
                    o.useDisplay ? fly(dom).setDisplayed(FALSE) : fly(dom).hide();
                    fly(dom).clearOpacity();
                    fly(dom).setPositioning(r.pos);
                    st.width = r.width;
                    st.height = r.height;
                    fly(dom).afterFx(o);
                }

                pt.by = fly(dom).switchStatements(anchor.toLowerCase(), function (v1, v2) { return [v1, v2]; }, {
                    t: [0, -h],
                    l: [-w, 0],
                    r: [w, 0],
                    b: [0, h],
                    tl: [-w, -h],
                    bl: [-w, h],
                    br: [w, h],
                    tr: [w, -h]
                });

                arguments.callee.anim = fly(dom).fxanim(a,
                o,
                MOTION,
                .5,
                EASEOUT, after);
            });
            return me;
        },


        syncFx: function () {
            var me = this;
            me.fxDefaults = Ext.apply(me.fxDefaults || {}, {
                block: FALSE,
                concurrent: TRUE,
                stopFx: FALSE
            });
            return me;
        },


        sequenceFx: function () {
            var me = this;
            me.fxDefaults = Ext.apply(me.fxDefaults || {}, {
                block: FALSE,
                concurrent: FALSE,
                stopFx: FALSE
            });
            return me;
        },


        nextFx: function () {
            var ef = getQueue(this.dom.id)[0];
            if (ef) {
                ef.call(this);
            }
        },


        hasActiveFx: function () {
            return getQueue(this.dom.id)[0];
        },


        stopFx: function (finish) {
            var me = this,
            id = me.dom.id;
            if (me.hasActiveFx()) {
                var cur = getQueue(id)[0];
                if (cur && cur.anim) {
                    if (cur.anim.isAnimated) {
                        setQueue(id, [cur]);
                        cur.anim.stop(finish !== undefined ? finish : TRUE);
                    } else {
                        setQueue(id, []);
                    }
                }
            }
            return me;
        },


        beforeFx: function (o) {
            if (this.hasActiveFx() && !o.concurrent) {
                if (o.stopFx) {
                    this.stopFx();
                    return TRUE;
                }
                return FALSE;
            }
            return TRUE;
        },


        hasFxBlock: function () {
            var q = getQueue(this.dom.id);
            return q && q[0] && q[0].block;
        },


        queueFx: function (o, fn) {
            var me = fly(this.dom);
            if (!me.hasFxBlock()) {
                Ext.applyIf(o, me.fxDefaults);
                if (!o.concurrent) {
                    var run = me.beforeFx(o);
                    fn.block = o.block;
                    getQueue(me.dom.id).push(fn);
                    if (run) {
                        me.nextFx();
                    }
                } else {
                    fn.call(me);
                }
            }
            return me;
        },


        fxWrap: function (pos, o, vis) {
            var dom = this.dom,
            wrap,
            wrapXY;
            if (!o.wrap || !(wrap = Ext.getDom(o.wrap))) {
                if (o.fixPosition) {
                    wrapXY = fly(dom).getXY();
                }
                var div = document.createElement("div");
                div.style.visibility = vis;
                wrap = dom.parentNode.insertBefore(div, dom);
                fly(wrap).setPositioning(pos);
                if (fly(wrap).isStyle(POSITION, "static")) {
                    fly(wrap).position("relative");
                }
                fly(dom).clearPositioning('auto');
                fly(wrap).clip();
                wrap.appendChild(dom);
                if (wrapXY) {
                    fly(wrap).setXY(wrapXY);
                }
            }
            return wrap;
        },


        fxUnwrap: function (wrap, pos, o) {
            var dom = this.dom;
            fly(dom).clearPositioning();
            fly(dom).setPositioning(pos);
            if (!o.wrap) {
                var pn = fly(wrap).dom.parentNode;
                pn.insertBefore(dom, wrap);
                fly(wrap).remove();
            }
        },


        getFxRestore: function () {
            var st = this.dom.style;
            return { pos: this.getPositioning(), width: st.width, height: st.height };
        },


        afterFx: function (o) {
            var dom = this.dom,
            id = dom.id;
            if (o.afterStyle) {
                fly(dom).setStyle(o.afterStyle);
            }
            if (o.afterCls) {
                fly(dom).addClass(o.afterCls);
            }
            if (o.remove == TRUE) {
                fly(dom).remove();
            }
            if (o.callback) {
                o.callback.call(o.scope, fly(dom));
            }
            if (!o.concurrent) {
                getQueue(id).shift();
                fly(dom).nextFx();
            }
        },


        fxanim: function (args, opt, animType, defaultDur, defaultEase, cb) {
            animType = animType || 'run';
            opt = opt || {};
            var anim = Ext.lib.Anim[animType](
                this.dom,
                args,
                (opt.duration || defaultDur) || .35,
                (opt.easing || defaultEase) || EASEOUT,
                cb,
                this
            );
            opt.anim = anim;
            return anim;
        }
    };


    Ext.Fx.resize = Ext.Fx.scale;



    Ext.Element.addMethods(Ext.Fx);
})();

Ext.CompositeElementLite = function (els, root) {

    this.elements = [];
    this.add(els, root);
    this.el = new Ext.Element.Flyweight();
};

Ext.CompositeElementLite.prototype = {
    isComposite: true,


    getElement: function (el) {

        var e = this.el;
        e.dom = el;
        e.id = el.id;
        return e;
    },


    transformElement: function (el) {
        return Ext.getDom(el);
    },


    getCount: function () {
        return this.elements.length;
    },

    add: function (els, root) {
        var me = this,
            elements = me.elements;
        if (!els) {
            return this;
        }
        if (typeof els == "string") {
            els = Ext.Element.selectorFunction(els, root);
        } else if (els.isComposite) {
            els = els.elements;
        } else if (!Ext.isIterable(els)) {
            els = [els];
        }

        for (var i = 0, len = els.length; i < len; ++i) {
            elements.push(me.transformElement(els[i]));
        }
        return me;
    },

    invoke: function (fn, args) {
        var me = this,
            els = me.elements,
            len = els.length,
            e,
            i;

        for (i = 0; i < len; i++) {
            e = els[i];
            if (e) {
                Ext.Element.prototype[fn].apply(me.getElement(e), args);
            }
        }
        return me;
    },

    item: function (index) {
        var me = this,
            el = me.elements[index],
            out = null;

        if (el) {
            out = me.getElement(el);
        }
        return out;
    },


    addListener: function (eventName, handler, scope, opt) {
        var els = this.elements,
            len = els.length,
            i, e;

        for (i = 0; i < len; i++) {
            e = els[i];
            if (e) {
                Ext.EventManager.on(e, eventName, handler, scope || e, opt);
            }
        }
        return this;
    },

    each: function (fn, scope) {
        var me = this,
            els = me.elements,
            len = els.length,
            i, e;

        for (i = 0; i < len; i++) {
            e = els[i];
            if (e) {
                e = this.getElement(e);
                if (fn.call(scope || e, e, me, i) === false) {
                    break;
                }
            }
        }
        return me;
    },


    fill: function (els) {
        var me = this;
        me.elements = [];
        me.add(els);
        return me;
    },


    filter: function (selector) {
        var els = [],
            me = this,
            fn = Ext.isFunction(selector) ? selector
                : function (el) {
                    return el.is(selector);
                };

        me.each(function (el, self, i) {
            if (fn(el, i) !== false) {
                els[els.length] = me.transformElement(el);
            }
        });

        me.elements = els;
        return me;
    },


    indexOf: function (el) {
        return this.elements.indexOf(this.transformElement(el));
    },


    replaceElement: function (el, replacement, domReplace) {
        var index = !isNaN(el) ? el : this.indexOf(el),
            d;
        if (index > -1) {
            replacement = Ext.getDom(replacement);
            if (domReplace) {
                d = this.elements[index];
                d.parentNode.insertBefore(replacement, d);
                Ext.removeNode(d);
            }
            this.elements.splice(index, 1, replacement);
        }
        return this;
    },


    clear: function () {
        this.elements = [];
    }
};

Ext.CompositeElementLite.prototype.on = Ext.CompositeElementLite.prototype.addListener;


Ext.CompositeElementLite.importElementMethods = function () {
    var fnName,
        ElProto = Ext.Element.prototype,
        CelProto = Ext.CompositeElementLite.prototype;

    for (fnName in ElProto) {
        if (typeof ElProto[fnName] == 'function') {
            (function (fnName) {
                CelProto[fnName] = CelProto[fnName] || function () {
                    return this.invoke(fnName, arguments);
                };
            }).call(CelProto, fnName);

        }
    }
};

Ext.CompositeElementLite.importElementMethods();

if (Ext.DomQuery) {
    Ext.Element.selectorFunction = Ext.DomQuery.select;
}


Ext.Element.select = function (selector, root) {
    var els;
    if (typeof selector == "string") {
        els = Ext.Element.selectorFunction(selector, root);
    } else if (selector.length !== undefined) {
        els = selector;
    } else {
        throw "Invalid selector";
    }
    return new Ext.CompositeElementLite(els);
};

Ext.select = Ext.Element.select;
(function () {
    var BEFOREREQUEST = "beforerequest",
        REQUESTCOMPLETE = "requestcomplete",
        REQUESTEXCEPTION = "requestexception",
        UNDEFINED = undefined,
        LOAD = 'load',
        POST = 'POST',
        GET = 'GET',
        WINDOW = window;


    Ext.data.Connection = function (config) {
        Ext.apply(this, config);
        this.addEvents(

            BEFOREREQUEST,

            REQUESTCOMPLETE,

            REQUESTEXCEPTION
        );
        Ext.data.Connection.superclass.constructor.call(this);
    };

    Ext.extend(Ext.data.Connection, Ext.util.Observable, {





        timeout: 30000,

        autoAbort: false,


        disableCaching: true,


        disableCachingParam: '_dc',


        request: function (o) {
            var me = this;
            if (me.fireEvent(BEFOREREQUEST, me, o)) {
                if (o.el) {
                    if (!Ext.isEmpty(o.indicatorText)) {
                        me.indicatorText = '<div class="loading-indicator">' + o.indicatorText + "</div>";
                    }
                    if (me.indicatorText) {
                        Ext.getDom(o.el).innerHTML = me.indicatorText;
                    }
                    o.success = (Ext.isFunction(o.success) ? o.success : function () { }).createInterceptor(function (response) {
                        Ext.getDom(o.el).innerHTML = response.responseText;
                    });
                }

                var p = o.params,
                    url = o.url || me.url,
                    method,
                    cb = { success: me.handleResponse,
                        failure: me.handleFailure,
                        scope: me,
                        argument: { options: o },
                        timeout: Ext.num(o.timeout, me.timeout)
                    },
                    form,
                    serForm;


                if (Ext.isFunction(p)) {
                    p = p.call(o.scope || WINDOW, o);
                }

                p = Ext.urlEncode(me.extraParams, Ext.isObject(p) ? Ext.urlEncode(p) : p);

                if (Ext.isFunction(url)) {
                    url = url.call(o.scope || WINDOW, o);
                }

                if ((form = Ext.getDom(o.form))) {
                    url = url || form.action;
                    if (o.isUpload || (/multipart\/form-data/i.test(form.getAttribute("enctype")))) {
                        return me.doFormUpload.call(me, o, p, url);
                    }
                    serForm = Ext.lib.Ajax.serializeForm(form);
                    p = p ? (p + '&' + serForm) : serForm;
                }

                method = o.method || me.method || ((p || o.xmlData || o.jsonData) ? POST : GET);

                if (method === GET && (me.disableCaching && o.disableCaching !== false) || o.disableCaching === true) {
                    var dcp = o.disableCachingParam || me.disableCachingParam;
                    url = Ext.urlAppend(url, dcp + '=' + (new Date().getTime()));
                }

                o.headers = Ext.apply(o.headers || {}, me.defaultHeaders || {});

                if (o.autoAbort === true || me.autoAbort) {
                    me.abort();
                }

                if ((method == GET || o.xmlData || o.jsonData) && p) {
                    url = Ext.urlAppend(url, p);
                    p = '';
                }
                return (me.transId = Ext.lib.Ajax.request(method, url, cb, p, o));
            } else {
                return o.callback ? o.callback.apply(o.scope, [o, UNDEFINED, UNDEFINED]) : null;
            }
        },


        isLoading: function (transId) {
            return transId ? Ext.lib.Ajax.isCallInProgress(transId) : !!this.transId;
        },


        abort: function (transId) {
            if (transId || this.isLoading()) {
                Ext.lib.Ajax.abort(transId || this.transId);
            }
        },


        handleResponse: function (response) {
            this.transId = false;
            var options = response.argument.options;
            response.argument = options ? options.argument : null;
            this.fireEvent(REQUESTCOMPLETE, this, response, options);
            if (options.success) {
                options.success.call(options.scope, response, options);
            }
            if (options.callback) {
                options.callback.call(options.scope, options, true, response);
            }
        },


        handleFailure: function (response, e) {
            this.transId = false;
            var options = response.argument.options;
            response.argument = options ? options.argument : null;
            this.fireEvent(REQUESTEXCEPTION, this, response, options, e);
            if (options.failure) {
                options.failure.call(options.scope, response, options);
            }
            if (options.callback) {
                options.callback.call(options.scope, options, false, response);
            }
        },


        doFormUpload: function (o, ps, url) {
            var id = Ext.id(),
                doc = document,
                frame = doc.createElement('iframe'),
                form = Ext.getDom(o.form),
                hiddens = [],
                hd,
                encoding = 'multipart/form-data',
                buf = {
                    target: form.target,
                    method: form.method,
                    encoding: form.encoding,
                    enctype: form.enctype,
                    action: form.action
                };


            Ext.fly(frame).set({
                id: id,
                name: id,
                cls: 'x-hidden',
                src: Ext.SSL_SECURE_URL
            });

            doc.body.appendChild(frame);


            if (Ext.isIE) {
                document.frames[id].name = id;
            }


            Ext.fly(form).set({
                target: id,
                method: POST,
                enctype: encoding,
                encoding: encoding,
                action: url || buf.action
            });


            Ext.iterate(Ext.urlDecode(ps, false), function (k, v) {
                hd = doc.createElement('input');
                Ext.fly(hd).set({
                    type: 'hidden',
                    value: v,
                    name: k
                });
                form.appendChild(hd);
                hiddens.push(hd);
            });

            function cb() {
                var me = this,

                    r = { responseText: '',
                        responseXML: null,
                        argument: o.argument
                    },
                    doc,
                    firstChild;

                try {
                    doc = frame.contentWindow.document || frame.contentDocument || WINDOW.frames[id].document;
                    if (doc) {
                        if (doc.body) {
                            if (/textarea/i.test((firstChild = doc.body.firstChild || {}).tagName)) {
                                r.responseText = firstChild.value;
                            } else {
                                r.responseText = doc.body.innerHTML;
                            }
                        }

                        r.responseXML = doc.XMLDocument || doc;
                    }
                }
                catch (e) { }

                Ext.EventManager.removeListener(frame, LOAD, cb, me);

                me.fireEvent(REQUESTCOMPLETE, me, r, o);

                function runCallback(fn, scope, args) {
                    if (Ext.isFunction(fn)) {
                        fn.apply(scope, args);
                    }
                }

                runCallback(o.success, o.scope, [r, o]);
                runCallback(o.callback, o.scope, [o, true, r]);

                if (!me.debugUploads) {
                    setTimeout(function () { Ext.removeNode(frame); }, 100);
                }
            }

            Ext.EventManager.on(frame, LOAD, cb, this);
            form.submit();

            Ext.fly(form).set(buf);
            Ext.each(hiddens, function (h) {
                Ext.removeNode(h);
            });
        }
    });
})();


Ext.Ajax = new Ext.data.Connection({

















    autoAbort: false,


    serializeForm: function (form) {
        return Ext.lib.Ajax.serializeForm(form);
    }
});

Ext.util.JSON = new (function () {
    var useHasOwn = !!{}.hasOwnProperty,
        isNative = function () {
            var useNative = null;

            return function () {
                if (useNative === null) {
                    useNative = Ext.USE_NATIVE_JSON && window.JSON && JSON.toString() == '[object JSON]';
                }

                return useNative;
            };
        } (),
        pad = function (n) {
            return n < 10 ? "0" + n : n;
        },
        doDecode = function (json) {
            return eval("(" + json + ")");
        },
        doEncode = function (o) {
            if (!Ext.isDefined(o) || o === null) {
                return "null";
            } else if (Ext.isArray(o)) {
                return encodeArray(o);
            } else if (Ext.isDate(o)) {
                return Ext.util.JSON.encodeDate(o);
            } else if (Ext.isString(o)) {
                return encodeString(o);
            } else if (typeof o == "number") {

                return isFinite(o) ? String(o) : "null";
            } else if (Ext.isBoolean(o)) {
                return String(o);
            } else {
                var a = ["{"], b, i, v;
                for (i in o) {

                    if (!o.getElementsByTagName) {
                        if (!useHasOwn || o.hasOwnProperty(i)) {
                            v = o[i];
                            switch (typeof v) {
                                case "undefined":
                                case "function":
                                case "unknown":
                                    break;
                                default:
                                    if (b) {
                                        a.push(',');
                                    }
                                    a.push(doEncode(i), ":",
                                        v === null ? "null" : doEncode(v));
                                    b = true;
                            }
                        }
                    }
                }
                a.push("}");
                return a.join("");
            }
        },
        m = {
            "\b": '\\b',
            "\t": '\\t',
            "\n": '\\n',
            "\f": '\\f',
            "\r": '\\r',
            '"': '\\"',
            "\\": '\\\\'
        },
        encodeString = function (s) {
            if (/["\\\x00-\x1f]/.test(s)) {
                return '"' + s.replace(/([\x00-\x1f\\"])/g, function (a, b) {
                    var c = m[b];
                    if (c) {
                        return c;
                    }
                    c = b.charCodeAt();
                    return "\\u00" +
                        Math.floor(c / 16).toString(16) +
                        (c % 16).toString(16);
                }) + '"';
            }
            return '"' + s + '"';
        },
        encodeArray = function (o) {
            var a = ["["], b, i, l = o.length, v;
            for (i = 0; i < l; i += 1) {
                v = o[i];
                switch (typeof v) {
                    case "undefined":
                    case "function":
                    case "unknown":
                        break;
                    default:
                        if (b) {
                            a.push(',');
                        }
                        a.push(v === null ? "null" : Ext.util.JSON.encode(v));
                        b = true;
                }
            }
            a.push("]");
            return a.join("");
        };


    this.encodeDate = function (o) {
        return '"' + o.getFullYear() + "-" +
                pad(o.getMonth() + 1) + "-" +
                pad(o.getDate()) + "T" +
                pad(o.getHours()) + ":" +
                pad(o.getMinutes()) + ":" +
                pad(o.getSeconds()) + '"';
    };


    this.encode = function () {
        var ec;
        return function (o) {
            if (!ec) {

                ec = isNative() ? JSON.stringify : doEncode;
            }
            return ec(o);
        };
    } ();



    this.decode = function () {
        var dc;
        return function (json) {
            if (!dc) {

                dc = isNative() ? JSON.parse : doDecode;
            }
            return dc(json);
        };
    } ();

})();

Ext.encode = Ext.util.JSON.encode;

Ext.decode = Ext.util.JSON.decode;

Ext.EventManager = function () {
    var docReadyEvent,
        docReadyProcId,
        docReadyState = false,
        DETECT_NATIVE = Ext.isGecko || Ext.isWebKit || Ext.isSafari,
        E = Ext.lib.Event,
        D = Ext.lib.Dom,
        DOC = document,
        WINDOW = window,
        DOMCONTENTLOADED = "DOMContentLoaded",
        COMPLETE = 'complete',
        propRe = /^(?:scope|delay|buffer|single|stopEvent|preventDefault|stopPropagation|normalized|args|delegate)$/,

        specialElCache = [];

    function getId(el) {
        var id = false,
            i = 0,
            len = specialElCache.length,
            skip = false,
            o;

        if (el) {
            if (el.getElementById || el.navigator) {

                for (; i < len; ++i) {
                    o = specialElCache[i];
                    if (o.el === el) {
                        id = o.id;
                        break;
                    }
                }
                if (!id) {

                    id = Ext.id(el);
                    specialElCache.push({
                        id: id,
                        el: el
                    });
                    skip = true;
                }
            } else {
                id = Ext.id(el);
            }
            if (!Ext.elCache[id]) {
                Ext.Element.addToCache(new Ext.Element(el), id);
                if (skip) {
                    Ext.elCache[id].skipGC = true;
                }
            }
        }
        return id;
    }


    function addListener(el, ename, fn, task, wrap, scope) {
        el = Ext.getDom(el);
        var id = getId(el),
            es = Ext.elCache[id].events,
            wfn;

        wfn = E.on(el, ename, wrap);
        es[ename] = es[ename] || [];


        es[ename].push([fn, wrap, scope, wfn, task]);





        if (el.addEventListener && ename == "mousewheel") {
            var args = ["DOMMouseScroll", wrap, false];
            el.addEventListener.apply(el, args);
            Ext.EventManager.addListener(WINDOW, 'unload', function () {
                el.removeEventListener.apply(el, args);
            });
        }


        if (el == DOC && ename == "mousedown") {
            Ext.EventManager.stoppedMouseDownEvent.addListener(wrap);
        }
    }

    function doScrollChk() {

        if (window != top) {
            return false;
        }

        try {
            DOC.documentElement.doScroll('left');
        } catch (e) {
            return false;
        }

        fireDocReady();
        return true;
    }

    function checkReadyState(e) {

        if (Ext.isIE && doScrollChk()) {
            return true;
        }
        if (DOC.readyState == COMPLETE) {
            fireDocReady();
            return true;
        }
        docReadyState || (docReadyProcId = setTimeout(arguments.callee, 2));
        return false;
    }

    var styles;
    function checkStyleSheets(e) {
        styles || (styles = Ext.query('style, link[rel=stylesheet]'));
        if (styles.length == DOC.styleSheets.length) {
            fireDocReady();
            return true;
        }
        docReadyState || (docReadyProcId = setTimeout(arguments.callee, 2));
        return false;
    }

    function OperaDOMContentLoaded(e) {
        DOC.removeEventListener(DOMCONTENTLOADED, arguments.callee, false);
        checkStyleSheets();
    }

    function fireDocReady(e) {
        if (!docReadyState) {
            docReadyState = true;

            if (docReadyProcId) {
                clearTimeout(docReadyProcId);
            }
            if (DETECT_NATIVE) {
                DOC.removeEventListener(DOMCONTENTLOADED, fireDocReady, false);
            }
            if (Ext.isIE && checkReadyState.bindIE) {
                DOC.detachEvent('onreadystatechange', checkReadyState);
            }
            E.un(WINDOW, "load", arguments.callee);
        }
        if (docReadyEvent && !Ext.isReady) {
            Ext.isReady = true;
            docReadyEvent.fire();
            docReadyEvent.listeners = [];
        }

    }

    function initDocReady() {
        docReadyEvent || (docReadyEvent = new Ext.util.Event());
        if (DETECT_NATIVE) {
            DOC.addEventListener(DOMCONTENTLOADED, fireDocReady, false);
        }

        if (Ext.isIE) {


            if (!checkReadyState()) {
                checkReadyState.bindIE = true;
                DOC.attachEvent('onreadystatechange', checkReadyState);
            }

        } else if (Ext.isOpera) {



            (DOC.readyState == COMPLETE && checkStyleSheets()) ||
                DOC.addEventListener(DOMCONTENTLOADED, OperaDOMContentLoaded, false);

        } else if (Ext.isWebKit) {

            checkReadyState();
        }

        E.on(WINDOW, "load", fireDocReady);
    }

    function createTargeted(h, o) {
        return function () {
            var args = Ext.toArray(arguments);
            if (o.target == Ext.EventObject.setEvent(args[0]).target) {
                h.apply(this, args);
            }
        };
    }

    function createBuffered(h, o, task) {
        return function (e) {

            task.delay(o.buffer, h, null, [new Ext.EventObjectImpl(e)]);
        };
    }

    function createSingle(h, el, ename, fn, scope) {
        return function (e) {
            Ext.EventManager.removeListener(el, ename, fn, scope);
            h(e);
        };
    }

    function createDelayed(h, o, fn) {
        return function (e) {
            var task = new Ext.util.DelayedTask(h);
            if (!fn.tasks) {
                fn.tasks = [];
            }
            fn.tasks.push(task);
            task.delay(o.delay || 10, h, null, [new Ext.EventObjectImpl(e)]);
        };
    }

    function listen(element, ename, opt, fn, scope) {
        var o = (!opt || typeof opt == "boolean") ? {} : opt,
            el = Ext.getDom(element), task;

        fn = fn || o.fn;
        scope = scope || o.scope;

        if (!el) {
            throw "Error listening for \"" + ename + '\". Element "' + element + '" doesn\'t exist.';
        }
        function h(e) {

            if (!Ext) {
                return;
            }
            e = Ext.EventObject.setEvent(e);
            var t;
            if (o.delegate) {
                if (!(t = e.getTarget(o.delegate, el))) {
                    return;
                }
            } else {
                t = e.target;
            }
            if (o.stopEvent) {
                e.stopEvent();
            }
            if (o.preventDefault) {
                e.preventDefault();
            }
            if (o.stopPropagation) {
                e.stopPropagation();
            }
            if (o.normalized === false) {
                e = e.browserEvent;
            }

            fn.call(scope || el, e, t, o);
        }
        if (o.target) {
            h = createTargeted(h, o);
        }
        if (o.delay) {
            h = createDelayed(h, o, fn);
        }
        if (o.single) {
            h = createSingle(h, el, ename, fn, scope);
        }
        if (o.buffer) {
            task = new Ext.util.DelayedTask(h);
            h = createBuffered(h, o, task);
        }

        addListener(el, ename, fn, task, h, scope);
        return h;
    }

    var pub = {

        addListener: function (element, eventName, fn, scope, options) {
            if (typeof eventName == 'object') {
                var o = eventName, e, val;
                for (e in o) {
                    val = o[e];
                    if (!propRe.test(e)) {
                        if (Ext.isFunction(val)) {

                            listen(element, e, o, val, o.scope);
                        } else {

                            listen(element, e, val);
                        }
                    }
                }
            } else {
                listen(element, eventName, options, fn, scope);
            }
        },


        removeListener: function (el, eventName, fn, scope) {
            el = Ext.getDom(el);
            var id = getId(el),
                f = el && (Ext.elCache[id].events)[eventName] || [],
                wrap, i, l, k, len, fnc;

            for (i = 0, len = f.length; i < len; i++) {


                if (Ext.isArray(fnc = f[i]) && fnc[0] == fn && (!scope || fnc[2] == scope)) {
                    if (fnc[4]) {
                        fnc[4].cancel();
                    }
                    k = fn.tasks && fn.tasks.length;
                    if (k) {
                        while (k--) {
                            fn.tasks[k].cancel();
                        }
                        delete fn.tasks;
                    }
                    wrap = fnc[1];
                    E.un(el, eventName, E.extAdapter ? fnc[3] : wrap);


                    if (wrap && el.addEventListener && eventName == "mousewheel") {
                        el.removeEventListener("DOMMouseScroll", wrap, false);
                    }


                    if (wrap && el == DOC && eventName == "mousedown") {
                        Ext.EventManager.stoppedMouseDownEvent.removeListener(wrap);
                    }

                    f.splice(i, 1);
                    if (f.length === 0) {
                        delete Ext.elCache[id].events[eventName];
                    }
                    for (k in Ext.elCache[id].events) {
                        return false;
                    }
                    Ext.elCache[id].events = {};
                    return false;
                }
            }
        },


        removeAll: function (el) {
            el = Ext.getDom(el);
            var id = getId(el),
                ec = Ext.elCache[id] || {},
                es = ec.events || {},
                f, i, len, ename, fn, k, wrap;

            for (ename in es) {
                if (es.hasOwnProperty(ename)) {
                    f = es[ename];

                    for (i = 0, len = f.length; i < len; i++) {
                        fn = f[i];
                        if (fn[4]) {
                            fn[4].cancel();
                        }
                        if (fn[0].tasks && (k = fn[0].tasks.length)) {
                            while (k--) {
                                fn[0].tasks[k].cancel();
                            }
                            delete fn.tasks;
                        }
                        wrap = fn[1];
                        E.un(el, ename, E.extAdapter ? fn[3] : wrap);


                        if (el.addEventListener && wrap && ename == "mousewheel") {
                            el.removeEventListener("DOMMouseScroll", wrap, false);
                        }


                        if (wrap && el == DOC && ename == "mousedown") {
                            Ext.EventManager.stoppedMouseDownEvent.removeListener(wrap);
                        }
                    }
                }
            }
            if (Ext.elCache[id]) {
                Ext.elCache[id].events = {};
            }
        },

        getListeners: function (el, eventName) {
            el = Ext.getDom(el);
            var id = getId(el),
                ec = Ext.elCache[id] || {},
                es = ec.events || {},
                results = [];
            if (es && es[eventName]) {
                return es[eventName];
            } else {
                return null;
            }
        },

        purgeElement: function (el, recurse, eventName) {
            el = Ext.getDom(el);
            var id = getId(el),
                ec = Ext.elCache[id] || {},
                es = ec.events || {},
                i, f, len;
            if (eventName) {
                if (es && es.hasOwnProperty(eventName)) {
                    f = es[eventName];
                    for (i = 0, len = f.length; i < len; i++) {
                        Ext.EventManager.removeListener(el, eventName, f[i][0]);
                    }
                }
            } else {
                Ext.EventManager.removeAll(el);
            }
            if (recurse && el && el.childNodes) {
                for (i = 0, len = el.childNodes.length; i < len; i++) {
                    Ext.EventManager.purgeElement(el.childNodes[i], recurse, eventName);
                }
            }
        },

        _unload: function () {
            var el;
            for (el in Ext.elCache) {
                Ext.EventManager.removeAll(el);
            }
            delete Ext.elCache;
            delete Ext.Element._flyweights;


            var c,
                conn,
                tid,
                ajax = Ext.lib.Ajax;
            (typeof ajax.conn == 'object') ? conn = ajax.conn : conn = {};
            for (tid in conn) {
                c = conn[tid];
                if (c) {
                    ajax.abort({ conn: c, tId: tid });
                }
            }
        },

        onDocumentReady: function (fn, scope, options) {
            if (Ext.isReady) {
                docReadyEvent || (docReadyEvent = new Ext.util.Event());
                docReadyEvent.addListener(fn, scope, options);
                docReadyEvent.fire();
                docReadyEvent.listeners = [];
            } else {
                if (!docReadyEvent) {
                    initDocReady();
                }
                options = options || {};
                options.delay = options.delay || 1;
                docReadyEvent.addListener(fn, scope, options);
            }
        },


        fireDocReady: fireDocReady
    };

    pub.on = pub.addListener;

    pub.un = pub.removeListener;

    pub.stoppedMouseDownEvent = new Ext.util.Event();
    return pub;
} ();

Ext.onReady = Ext.EventManager.onDocumentReady;



(function () {
    var initExtCss = function () {

        var bd = document.body || document.getElementsByTagName('body')[0];
        if (!bd) {
            return false;
        }

        var cls = [' ',
                Ext.isIE ? "ext-ie " + (Ext.isIE6 ? 'ext-ie6' : (Ext.isIE7 ? 'ext-ie7' : 'ext-ie8'))
                : Ext.isGecko ? "ext-gecko " + (Ext.isGecko2 ? 'ext-gecko2' : 'ext-gecko3')
                : Ext.isOpera ? "ext-opera"
                : Ext.isWebKit ? "ext-webkit" : ""];

        if (Ext.isSafari) {
            cls.push("ext-safari " + (Ext.isSafari2 ? 'ext-safari2' : (Ext.isSafari3 ? 'ext-safari3' : 'ext-safari4')));
        } else if (Ext.isChrome) {
            cls.push("ext-chrome");
        }

        if (Ext.isMac) {
            cls.push("ext-mac");
        }
        if (Ext.isLinux) {
            cls.push("ext-linux");
        }


        if (Ext.isStrict || Ext.isBorderBox) {
            var p = bd.parentNode;
            if (p) {
                Ext.fly(p, '_internal').addClass(((Ext.isStrict && Ext.isIE) || (!Ext.enableForcedBoxModel && !Ext.isIE)) ? ' ext-strict' : ' ext-border-box');
            }
        }


        if (Ext.enableForcedBoxModel && !Ext.isIE) {
            Ext.isForcedBorderBox = true;
            cls.push("ext-forced-border-box");
        }

        Ext.fly(bd, '_internal').addClass(cls);
        return true;
    };


    Ext.isReady = initExtCss();

    if (!Ext.isReady) {
        Ext.onReady(initExtCss);
    }
})();


(function () {
    var supports = Ext.apply(Ext.supports, {

        correctRightMargin: true,


        correctTransparentColor: true,


        cssFloat: true
    });

    var supportTests = function () {
        var div = document.createElement('div'),
                doc = document,
                view,
                last;

        div.innerHTML = '<div style="height:30px;width:50px;"><div style="height:20px;width:20px;"></div></div><div style="float:left;background-color:transparent;">';
        doc.body.appendChild(div);
        last = div.lastChild;

        if ((view = doc.defaultView)) {
            if (view.getComputedStyle(div.firstChild.firstChild, null).marginRight != '0px') {
                supports.correctRightMargin = false;
            }
            if (view.getComputedStyle(last, null).backgroundColor != 'transparent') {
                supports.correctTransparentColor = false;
            }
        }
        supports.cssFloat = !!last.style.cssFloat;
        doc.body.removeChild(div);
    };

    if (Ext.isReady) {
        supportTests();
    } else {
        Ext.onReady(supportTests);
    }
})();



Ext.EventObject = function () {
    var E = Ext.lib.Event,
        clickRe = /(dbl)?click/,

        safariKeys = {
            3: 13,
            63234: 37,
            63235: 39,
            63232: 38,
            63233: 40,
            63276: 33,
            63277: 34,
            63272: 46,
            63273: 36,
            63275: 35
        },

        btnMap = Ext.isIE ? { 1: 0, 4: 1, 2: 2} : { 0: 0, 1: 1, 2: 2 };

    Ext.EventObjectImpl = function (e) {
        if (e) {
            this.setEvent(e.browserEvent || e);
        }
    };

    Ext.EventObjectImpl.prototype = {

        setEvent: function (e) {
            var me = this;
            if (e == me || (e && e.browserEvent)) {
                return e;
            }
            me.browserEvent = e;
            if (e) {

                me.button = e.button ? btnMap[e.button] : (e.which ? e.which - 1 : -1);
                if (clickRe.test(e.type) && me.button == -1) {
                    me.button = 0;
                }
                me.type = e.type;
                me.shiftKey = e.shiftKey;

                me.ctrlKey = e.ctrlKey || e.metaKey || false;
                me.altKey = e.altKey;

                me.keyCode = e.keyCode;
                me.charCode = e.charCode;

                me.target = E.getTarget(e);

                me.xy = E.getXY(e);
            } else {
                me.button = -1;
                me.shiftKey = false;
                me.ctrlKey = false;
                me.altKey = false;
                me.keyCode = 0;
                me.charCode = 0;
                me.target = null;
                me.xy = [0, 0];
            }
            return me;
        },


        stopEvent: function () {
            var me = this;
            if (me.browserEvent) {
                if (me.browserEvent.type == 'mousedown') {
                    Ext.EventManager.stoppedMouseDownEvent.fire(me);
                }
                E.stopEvent(me.browserEvent);
            }
        },


        preventDefault: function () {
            if (this.browserEvent) {
                E.preventDefault(this.browserEvent);
            }
        },


        stopPropagation: function () {
            var me = this;
            if (me.browserEvent) {
                if (me.browserEvent.type == 'mousedown') {
                    Ext.EventManager.stoppedMouseDownEvent.fire(me);
                }
                E.stopPropagation(me.browserEvent);
            }
        },


        getCharCode: function () {
            return this.charCode || this.keyCode;
        },


        getKey: function () {
            return this.normalizeKey(this.keyCode || this.charCode);
        },


        normalizeKey: function (k) {
            return Ext.isSafari ? (safariKeys[k] || k) : k;
        },


        getPageX: function () {
            return this.xy[0];
        },


        getPageY: function () {
            return this.xy[1];
        },


        getXY: function () {
            return this.xy;
        },


        getTarget: function (selector, maxDepth, returnEl) {
            return selector ? Ext.fly(this.target).findParent(selector, maxDepth, returnEl) : (returnEl ? Ext.get(this.target) : this.target);
        },


        getRelatedTarget: function () {
            return this.browserEvent ? E.getRelatedTarget(this.browserEvent) : null;
        },


        getWheelDelta: function () {
            var e = this.browserEvent;
            var delta = 0;
            if (e.wheelDelta) {
                delta = e.wheelDelta / 120;
            } else if (e.detail) {
                delta = -e.detail / 3;
            }
            return delta;
        },


        within: function (el, related, allowEl) {
            if (el) {
                var t = this[related ? "getRelatedTarget" : "getTarget"]();
                return t && ((allowEl ? (t == Ext.getDom(el)) : false) || Ext.fly(el).contains(t));
            }
            return false;
        }
    };

    return new Ext.EventObjectImpl();
} ();


Ext.ns("Ext.grid", "Ext.list", "Ext.dd", "Ext.tree", "Ext.form", "Ext.menu",
       "Ext.state", "Ext.layout", "Ext.app", "Ext.ux", "Ext.chart", "Ext.direct");


Ext.apply(Ext, function () {
    var E = Ext,
        idSeed = 0,
        scrollWidth = null;

    return {

        emptyFn: function () { },


        BLANK_IMAGE_URL: Ext.isIE6 || Ext.isIE7 || Ext.isAir ?
                            'http:/' + '/www.extjs.com/s.gif' :
                            '',

        extendX: function (supr, fn) {
            return Ext.extend(supr, fn(supr.prototype));
        },


        getDoc: function () {
            return Ext.get(document);
        },


        num: function (v, defaultValue) {
            v = Number(Ext.isEmpty(v) || Ext.isArray(v) || typeof v == 'boolean' || (typeof v == 'string' && v.trim().length == 0) ? NaN : v);
            return isNaN(v) ? defaultValue : v;
        },


        value: function (v, defaultValue, allowBlank) {
            return Ext.isEmpty(v, allowBlank) ? defaultValue : v;
        },


        escapeRe: function (s) {
            return s.replace(/([-.*+?^${}()|[\]\/\\])/g, "\\$1");
        },

        sequence: function (o, name, fn, scope) {
            o[name] = o[name].createSequence(fn, scope);
        },


        addBehaviors: function (o) {
            if (!Ext.isReady) {
                Ext.onReady(function () {
                    Ext.addBehaviors(o);
                });
            } else {
                var cache = {},
                    parts,
                    b,
                    s;
                for (b in o) {
                    if ((parts = b.split('@'))[1]) {
                        s = parts[0];
                        if (!cache[s]) {
                            cache[s] = Ext.select(s);
                        }
                        cache[s].on(parts[1], o[b]);
                    }
                }
                cache = null;
            }
        },


        getScrollBarWidth: function (force) {
            if (!Ext.isReady) {
                return 0;
            }

            if (force === true || scrollWidth === null) {

                var div = Ext.getBody().createChild('<div class="x-hide-offsets" style="width:100px;height:50px;overflow:hidden;"><div style="height:200px;"></div></div>'),
                    child = div.child('div', true);
                var w1 = child.offsetWidth;
                div.setStyle('overflow', (Ext.isWebKit || Ext.isGecko) ? 'auto' : 'scroll');
                var w2 = child.offsetWidth;
                div.remove();

                scrollWidth = w1 - w2 + 2;
            }
            return scrollWidth;
        },



        combine: function () {
            var as = arguments, l = as.length, r = [];
            for (var i = 0; i < l; i++) {
                var a = as[i];
                if (Ext.isArray(a)) {
                    r = r.concat(a);
                } else if (a.length !== undefined && !a.substr) {
                    r = r.concat(Array.prototype.slice.call(a, 0));
                } else {
                    r.push(a);
                }
            }
            return r;
        },


        copyTo: function (dest, source, names) {
            if (typeof names == 'string') {
                names = names.split(/[,;\s]/);
            }
            Ext.each(names, function (name) {
                if (source.hasOwnProperty(name)) {
                    dest[name] = source[name];
                }
            }, this);
            return dest;
        },


        destroy: function () {
            Ext.each(arguments, function (arg) {
                if (arg) {
                    if (Ext.isArray(arg)) {
                        this.destroy.apply(this, arg);
                    } else if (typeof arg.destroy == 'function') {
                        arg.destroy();
                    } else if (arg.dom) {
                        arg.remove();
                    }
                }
            }, this);
        },


        destroyMembers: function (o, arg1, arg2, etc) {
            for (var i = 1, a = arguments, len = a.length; i < len; i++) {
                Ext.destroy(o[a[i]]);
                delete o[a[i]];
            }
        },


        clean: function (arr) {
            var ret = [];
            Ext.each(arr, function (v) {
                if (!!v) {
                    ret.push(v);
                }
            });
            return ret;
        },


        unique: function (arr) {
            var ret = [],
                collect = {};

            Ext.each(arr, function (v) {
                if (!collect[v]) {
                    ret.push(v);
                }
                collect[v] = true;
            });
            return ret;
        },


        flatten: function (arr) {
            var worker = [];
            function rFlatten(a) {
                Ext.each(a, function (v) {
                    if (Ext.isArray(v)) {
                        rFlatten(v);
                    } else {
                        worker.push(v);
                    }
                });
                return worker;
            }
            return rFlatten(arr);
        },


        min: function (arr, comp) {
            var ret = arr[0];
            comp = comp || function (a, b) { return a < b ? -1 : 1; };
            Ext.each(arr, function (v) {
                ret = comp(ret, v) == -1 ? ret : v;
            });
            return ret;
        },


        max: function (arr, comp) {
            var ret = arr[0];
            comp = comp || function (a, b) { return a > b ? 1 : -1; };
            Ext.each(arr, function (v) {
                ret = comp(ret, v) == 1 ? ret : v;
            });
            return ret;
        },


        mean: function (arr) {
            return arr.length > 0 ? Ext.sum(arr) / arr.length : undefined;
        },


        sum: function (arr) {
            var ret = 0;
            Ext.each(arr, function (v) {
                ret += v;
            });
            return ret;
        },


        partition: function (arr, truth) {
            var ret = [[], []];
            Ext.each(arr, function (v, i, a) {
                ret[(truth && truth(v, i, a)) || (!truth && v) ? 0 : 1].push(v);
            });
            return ret;
        },


        invoke: function (arr, methodName) {
            var ret = [],
                args = Array.prototype.slice.call(arguments, 2);
            Ext.each(arr, function (v, i) {
                if (v && typeof v[methodName] == 'function') {
                    ret.push(v[methodName].apply(v, args));
                } else {
                    ret.push(undefined);
                }
            });
            return ret;
        },


        pluck: function (arr, prop) {
            var ret = [];
            Ext.each(arr, function (v) {
                ret.push(v[prop]);
            });
            return ret;
        },


        zip: function () {
            var parts = Ext.partition(arguments, function (val) { return typeof val != 'function'; }),
                arrs = parts[0],
                fn = parts[1][0],
                len = Ext.max(Ext.pluck(arrs, "length")),
                ret = [];

            for (var i = 0; i < len; i++) {
                ret[i] = [];
                if (fn) {
                    ret[i] = fn.apply(fn, Ext.pluck(arrs, i));
                } else {
                    for (var j = 0, aLen = arrs.length; j < aLen; j++) {
                        ret[i].push(arrs[j][i]);
                    }
                }
            }
            return ret;
        },


        getCmp: function (id) {
            return Ext.ComponentMgr.get(id);
        },


        useShims: E.isIE6 || (E.isMac && E.isGecko2),



        type: function (o) {
            if (o === undefined || o === null) {
                return false;
            }
            if (o.htmlElement) {
                return 'element';
            }
            var t = typeof o;
            if (t == 'object' && o.nodeName) {
                switch (o.nodeType) {
                    case 1: return 'element';
                    case 3: return (/\S/).test(o.nodeValue) ? 'textnode' : 'whitespace';
                }
            }
            if (t == 'object' || t == 'function') {
                switch (o.constructor) {
                    case Array: return 'array';
                    case RegExp: return 'regexp';
                    case Date: return 'date';
                }
                if (typeof o.length == 'number' && typeof o.item == 'function') {
                    return 'nodelist';
                }
            }
            return t;
        },

        intercept: function (o, name, fn, scope) {
            o[name] = o[name].createInterceptor(fn, scope);
        },


        callback: function (cb, scope, args, delay) {
            if (typeof cb == 'function') {
                if (delay) {
                    cb.defer(delay, scope, args || []);
                } else {
                    cb.apply(scope, args || []);
                }
            }
        }
    };
} ());


Ext.apply(Function.prototype, {

    createSequence: function (fcn, scope) {
        var method = this;
        return (typeof fcn != 'function') ?
                this :
                function () {
                    var retval = method.apply(this || window, arguments);
                    fcn.apply(scope || this || window, arguments);
                    return retval;
                };
    }
});



Ext.applyIf(String, {


    escape: function (string) {
        return string.replace(/('|\\)/g, "\\$1");
    },


    leftPad: function (val, size, ch) {
        var result = String(val);
        if (!ch) {
            ch = " ";
        }
        while (result.length < size) {
            result = ch + result;
        }
        return result;
    }
});


String.prototype.toggle = function (value, other) {
    return this == value ? other : value;
};


String.prototype.trim = function () {
    var re = /^\s+|\s+$/g;
    return function () { return this.replace(re, ""); };
} ();



Date.prototype.getElapsed = function (date) {
    return Math.abs((date || new Date()).getTime() - this.getTime());
};



Ext.applyIf(Number.prototype, {

    constrain: function (min, max) {
        return Math.min(Math.max(this, min), max);
    }
});
Ext.lib.Dom.getRegion = function (el) {
    return Ext.lib.Region.getRegion(el);
}; Ext.lib.Region = function (t, r, b, l) {
    var me = this;
    me.top = t;
    me[1] = t;
    me.right = r;
    me.bottom = b;
    me.left = l;
    me[0] = l;
};

Ext.lib.Region.prototype = {
    contains: function (region) {
        var me = this;
        return (region.left >= me.left &&
                     region.right <= me.right &&
                     region.top >= me.top &&
                     region.bottom <= me.bottom);

    },

    getArea: function () {
        var me = this;
        return ((me.bottom - me.top) * (me.right - me.left));
    },

    intersect: function (region) {
        var me = this,
            	t = Math.max(me.top, region.top),
            	r = Math.min(me.right, region.right),
            	b = Math.min(me.bottom, region.bottom),
            	l = Math.max(me.left, region.left);

        if (b >= t && r >= l) {
            return new Ext.lib.Region(t, r, b, l);
        }
    },

    union: function (region) {
        var me = this,
            	t = Math.min(me.top, region.top),
            	r = Math.max(me.right, region.right),
            	b = Math.max(me.bottom, region.bottom),
            	l = Math.min(me.left, region.left);

        return new Ext.lib.Region(t, r, b, l);
    },

    constrainTo: function (r) {
        var me = this;
        me.top = me.top.constrain(r.top, r.bottom);
        me.bottom = me.bottom.constrain(r.top, r.bottom);
        me.left = me.left.constrain(r.left, r.right);
        me.right = me.right.constrain(r.left, r.right);
        return me;
    },

    adjust: function (t, l, b, r) {
        var me = this;
        me.top += t;
        me.left += l;
        me.right += r;
        me.bottom += b;
        return me;
    }
};

Ext.lib.Region.getRegion = function (el) {
    var p = Ext.lib.Dom.getXY(el),
        	t = p[1],
        	r = p[0] + el.offsetWidth,
        	b = p[1] + el.offsetHeight,
        	l = p[0];

    return new Ext.lib.Region(t, r, b, l);
}; Ext.lib.Point = function (x, y) {
    if (Ext.isArray(x)) {
        y = x[1];
        x = x[0];
    }
    var me = this;
    me.x = me.right = me.left = me[0] = x;
    me.y = me.top = me.bottom = me[1] = y;
};

Ext.lib.Point.prototype = new Ext.lib.Region();

Ext.apply(Ext.DomHelper,
function () {
    var pub,
        afterbegin = 'afterbegin',
        afterend = 'afterend',
        beforebegin = 'beforebegin',
        beforeend = 'beforeend',
        confRe = /tag|children|cn|html$/i;


    function doInsert(el, o, returnElement, pos, sibling, append) {
        el = Ext.getDom(el);
        var newNode;
        if (pub.useDom) {
            newNode = createDom(o, null);
            if (append) {
                el.appendChild(newNode);
            } else {
                (sibling == 'firstChild' ? el : el.parentNode).insertBefore(newNode, el[sibling] || el);
            }
        } else {
            newNode = Ext.DomHelper.insertHtml(pos, el, Ext.DomHelper.createHtml(o));
        }
        return returnElement ? Ext.get(newNode, true) : newNode;
    }



    function createDom(o, parentNode) {
        var el,
            doc = document,
            useSet,
            attr,
            val,
            cn;

        if (Ext.isArray(o)) {
            el = doc.createDocumentFragment();
            for (var i = 0, l = o.length; i < l; i++) {
                createDom(o[i], el);
            }
        } else if (typeof o == 'string') {
            el = doc.createTextNode(o);
        } else {
            el = doc.createElement(o.tag || 'div');
            useSet = !!el.setAttribute;
            for (var attr in o) {
                if (!confRe.test(attr)) {
                    val = o[attr];
                    if (attr == 'cls') {
                        el.className = val;
                    } else {
                        if (useSet) {
                            el.setAttribute(attr, val);
                        } else {
                            el[attr] = val;
                        }
                    }
                }
            }
            Ext.DomHelper.applyStyles(el, o.style);

            if ((cn = o.children || o.cn)) {
                createDom(cn, el);
            } else if (o.html) {
                el.innerHTML = o.html;
            }
        }
        if (parentNode) {
            parentNode.appendChild(el);
        }
        return el;
    }

    pub = {

        createTemplate: function (o) {
            var html = Ext.DomHelper.createHtml(o);
            return new Ext.Template(html);
        },


        useDom: false,


        insertBefore: function (el, o, returnElement) {
            return doInsert(el, o, returnElement, beforebegin);
        },


        insertAfter: function (el, o, returnElement) {
            return doInsert(el, o, returnElement, afterend, 'nextSibling');
        },


        insertFirst: function (el, o, returnElement) {
            return doInsert(el, o, returnElement, afterbegin, 'firstChild');
        },


        append: function (el, o, returnElement) {
            return doInsert(el, o, returnElement, beforeend, '', true);
        },


        createDom: createDom
    };
    return pub;
} ());

Ext.apply(Ext.Template.prototype, {

    disableFormats: false,



    re: /\{([\w-]+)(?:\:([\w\.]*)(?:\((.*?)?\))?)?\}/g,
    argsRe: /^\s*['"](.*)["']\s*$/,
    compileARe: /\\/g,
    compileBRe: /(\r\n|\n)/g,
    compileCRe: /'/g,

    /**
    * Returns an HTML fragment of this template with the specified values applied.
    * @param {Object/Array} values The template values. Can be an array if your params are numeric (i.e. {0}) or an object (i.e. {foo: 'bar'})
    * @return {String} The HTML fragment
    * @hide repeat doc
    */
    applyTemplate: function (values) {
        var me = this,
            useF = me.disableFormats !== true,
            fm = Ext.util.Format,
            tpl = me;

        if (me.compiled) {
            return me.compiled(values);
        }
        function fn(m, name, format, args) {
            if (format && useF) {
                if (format.substr(0, 5) == "this.") {
                    return tpl.call(format.substr(5), values[name], values);
                } else {
                    if (args) {
                        // quoted values are required for strings in compiled templates,
                        // but for non compiled we need to strip them
                        // quoted reversed for jsmin
                        var re = me.argsRe;
                        args = args.split(',');
                        for (var i = 0, len = args.length; i < len; i++) {
                            args[i] = args[i].replace(re, "$1");
                        }
                        args = [values[name]].concat(args);
                    } else {
                        args = [values[name]];
                    }
                    return fm[format].apply(fm, args);
                }
            } else {
                return values[name] !== undefined ? values[name] : "";
            }
        }
        return me.html.replace(me.re, fn);
    },

    /**
    * Compiles the template into an internal function, eliminating the RegEx overhead.
    * @return {Ext.Template} this
    * @hide repeat doc
    */
    compile: function () {
        var me = this,
            fm = Ext.util.Format,
            useF = me.disableFormats !== true,
            sep = Ext.isGecko ? "+" : ",",
            body;

        function fn(m, name, format, args) {
            if (format && useF) {
                args = args ? ',' + args : "";
                if (format.substr(0, 5) != "this.") {
                    format = "fm." + format + '(';
                } else {
                    format = 'this.call("' + format.substr(5) + '", ';
                    args = ", values";
                }
            } else {
                args = ''; format = "(values['" + name + "'] == undefined ? '' : ";
            }
            return "'" + sep + format + "values['" + name + "']" + args + ")" + sep + "'";
        }

        // branched to use + in gecko and [].join() in others
        if (Ext.isGecko) {
            body = "this.compiled = function(values){ return '" +
                   me.html.replace(me.compileARe, '\\\\').replace(me.compileBRe, '\\n').replace(me.compileCRe, "\\'").replace(me.re, fn) +
                    "';};";
        } else {
            body = ["this.compiled = function(values){ return ['"];
            body.push(me.html.replace(me.compileARe, '\\\\').replace(me.compileBRe, '\\n').replace(me.compileCRe, "\\'").replace(me.re, fn));
            body.push("'].join('');};");
            body = body.join('');
        }
        eval(body);
        return me;
    },

    // private function used to call members
    call: function (fnName, value, allValues) {
        return this[fnName](value, allValues);
    }
});
Ext.Template.prototype.apply = Ext.Template.prototype.applyTemplate;
/**
* @class Ext.util.Functions
* @singleton
*/
Ext.util.Functions = {
    /**
    * Creates an interceptor function. The passed function is called before the original one. If it returns false,
    * the original one is not called. The resulting function returns the results of the original function.
    * The passed function is called with the parameters of the original function. Example usage:
    * <pre><code>
    var sayHi = function(name){
    alert('Hi, ' + name);
    }

    sayHi('Fred'); // alerts "Hi, Fred"

    // create a new function that validates input without
    // directly modifying the original function:
    var sayHiToFriend = Ext.createInterceptor(sayHi, function(name){
    return name == 'Brian';
    });

    sayHiToFriend('Fred');  // no alert
    sayHiToFriend('Brian'); // alerts "Hi, Brian"
    </code></pre>
    * @param {Function} origFn The original function.
    * @param {Function} newFn The function to call before the original
    * @param {Object} scope (optional) The scope (<code><b>this</b></code> reference) in which the passed function is executed.
    * <b>If omitted, defaults to the scope in which the original function is called or the browser window.</b>
    * @return {Function} The new function
    */
    createInterceptor: function (origFn, newFn, scope) {
        var method = origFn;
        if (!Ext.isFunction(newFn)) {
            return origFn;
        }
        else {
            return function () {
                var me = this,
                    args = arguments;
                newFn.target = me;
                newFn.method = origFn;
                return (newFn.apply(scope || me || window, args) !== false) ?
                        origFn.apply(me || window, args) :
                        null;
            };
        }
    },

    /**
    * Creates a delegate (callback) that sets the scope to obj.
    * Call directly on any function. Example: <code>Ext.createDelegate(this.myFunction, this, [arg1, arg2])</code>
    * Will create a function that is automatically scoped to obj so that the <tt>this</tt> variable inside the
    * callback points to obj. Example usage:
    * <pre><code>
    var sayHi = function(name){
    // Note this use of "this.text" here.  This function expects to
    // execute within a scope that contains a text property.  In this
    // example, the "this" variable is pointing to the btn object that
    // was passed in createDelegate below.
    alert('Hi, ' + name + '. You clicked the "' + this.text + '" button.');
    }

    var btn = new Ext.Button({
    text: 'Say Hi',
    renderTo: Ext.getBody()
    });

    // This callback will execute in the scope of the
    // button instance. Clicking the button alerts
    // "Hi, Fred. You clicked the "Say Hi" button."
    btn.on('click', Ext.createDelegate(sayHi, btn, ['Fred']));
    </code></pre>
    * @param {Function} fn The function to delegate.
    * @param {Object} scope (optional) The scope (<code><b>this</b></code> reference) in which the function is executed.
    * <b>If omitted, defaults to the browser window.</b>
    * @param {Array} args (optional) Overrides arguments for the call. (Defaults to the arguments passed by the caller)
    * @param {Boolean/Number} appendArgs (optional) if True args are appended to call args instead of overriding,
    * if a number the args are inserted at the specified position
    * @return {Function} The new function
    */
    createDelegate: function (fn, obj, args, appendArgs) {
        if (!Ext.isFunction(fn)) {
            return fn;
        }
        return function () {
            var callArgs = args || arguments;
            if (appendArgs === true) {
                callArgs = Array.prototype.slice.call(arguments, 0);
                callArgs = callArgs.concat(args);
            }
            else if (Ext.isNumber(appendArgs)) {
                callArgs = Array.prototype.slice.call(arguments, 0);
                // copy arguments first
                var applyArgs = [appendArgs, 0].concat(args);
                // create method call params
                Array.prototype.splice.apply(callArgs, applyArgs);
                // splice them in
            }
            return fn.apply(obj || window, callArgs);
        };
    },

    /**
    * Calls this function after the number of millseconds specified, optionally in a specific scope. Example usage:
    * <pre><code>
    var sayHi = function(name){
    alert('Hi, ' + name);
    }

    // executes immediately:
    sayHi('Fred');

    // executes after 2 seconds:
    Ext.defer(sayHi, 2000, this, ['Fred']);

    // this syntax is sometimes useful for deferring
    // execution of an anonymous function:
    Ext.defer(function(){
    alert('Anonymous');
    }, 100);
    </code></pre>
    * @param {Function} fn The function to defer.
    * @param {Number} millis The number of milliseconds for the setTimeout call (if less than or equal to 0 the function is executed immediately)
    * @param {Object} scope (optional) The scope (<code><b>this</b></code> reference) in which the function is executed.
    * <b>If omitted, defaults to the browser window.</b>
    * @param {Array} args (optional) Overrides arguments for the call. (Defaults to the arguments passed by the caller)
    * @param {Boolean/Number} appendArgs (optional) if True args are appended to call args instead of overriding,
    * if a number the args are inserted at the specified position
    * @return {Number} The timeout id that can be used with clearTimeout
    */
    defer: function (fn, millis, obj, args, appendArgs) {
        fn = Ext.util.Functions.createDelegate(fn, obj, args, appendArgs);
        if (millis > 0) {
            return setTimeout(fn, millis);
        }
        fn();
        return 0;
    },


    /**
    * Create a combined function call sequence of the original function + the passed function.
    * The resulting function returns the results of the original function.
    * The passed fcn is called with the parameters of the original function. Example usage:
    * 

    var sayHi = function(name){
    alert('Hi, ' + name);
    }

    sayHi('Fred'); // alerts "Hi, Fred"

    var sayGoodbye = Ext.createSequence(sayHi, function(name){
    alert('Bye, ' + name);
    });

    sayGoodbye('Fred'); // both alerts show

    * @param {Function} origFn The original function.
    * @param {Function} newFn The function to sequence
    * @param {Object} scope (optional) The scope (this reference) in which the passed function is executed.
    * If omitted, defaults to the scope in which the original function is called or the browser window.
    * @return {Function} The new function
    */
    createSequence: function (origFn, newFn, scope) {
        if (!Ext.isFunction(newFn)) {
            return origFn;
        }
        else {
            return function () {
                var retval = origFn.apply(this || window, arguments);
                newFn.apply(scope || this || window, arguments);
                return retval;
            };
        }
    }
};

/**
* Shorthand for {@link Ext.util.Functions#defer}   
* @param {Function} fn The function to defer.
* @param {Number} millis The number of milliseconds for the setTimeout call (if less than or equal to 0 the function is executed immediately)
* @param {Object} scope (optional) The scope (<code><b>this</b></code> reference) in which the function is executed.
* <b>If omitted, defaults to the browser window.</b>
* @param {Array} args (optional) Overrides arguments for the call. (Defaults to the arguments passed by the caller)
* @param {Boolean/Number} appendArgs (optional) if True args are appended to call args instead of overriding,
* if a number the args are inserted at the specified position
* @return {Number} The timeout id that can be used with clearTimeout
* @member Ext
* @method defer
*/

Ext.defer = Ext.util.Functions.defer;

/**
* Shorthand for {@link Ext.util.Functions#createInterceptor}   
* @param {Function} origFn The original function.
* @param {Function} newFn The function to call before the original
* @param {Object} scope (optional) The scope (<code><b>this</b></code> reference) in which the passed function is executed.
* <b>If omitted, defaults to the scope in which the original function is called or the browser window.</b>
* @return {Function} The new function
* @member Ext
* @method defer
*/

Ext.createInterceptor = Ext.util.Functions.createInterceptor;

/**
* Shorthand for {@link Ext.util.Functions#createSequence}
* @param {Function} origFn The original function.
* @param {Function} newFn The function to sequence
* @param {Object} scope (optional) The scope (this reference) in which the passed function is executed.
* If omitted, defaults to the scope in which the original function is called or the browser window.
* @return {Function} The new function
* @member Ext
* @method defer
*/

Ext.createSequence = Ext.util.Functions.createSequence;

/**
* Shorthand for {@link Ext.util.Functions#createDelegate}
* @param {Function} fn The function to delegate.
* @param {Object} scope (optional) The scope (<code><b>this</b></code> reference) in which the function is executed.
* <b>If omitted, defaults to the browser window.</b>
* @param {Array} args (optional) Overrides arguments for the call. (Defaults to the arguments passed by the caller)
* @param {Boolean/Number} appendArgs (optional) if True args are appended to call args instead of overriding,
* if a number the args are inserted at the specified position
* @return {Function} The new function
* @member Ext
* @method defer
*/
Ext.createDelegate = Ext.util.Functions.createDelegate;
/**
* @class Ext.util.Observable
*/
Ext.apply(Ext.util.Observable.prototype, function () {
    // this is considered experimental (along with beforeMethod, afterMethod, removeMethodListener?)
    // allows for easier interceptor and sequences, including cancelling and overwriting the return value of the call
    // private
    function getMethodEvent(method) {
        var e = (this.methodEvents = this.methodEvents ||
        {})[method], returnValue, v, cancel, obj = this;

        if (!e) {
            this.methodEvents[method] = e = {};
            e.originalFn = this[method];
            e.methodName = method;
            e.before = [];
            e.after = [];

            var makeCall = function (fn, scope, args) {
                if ((v = fn.apply(scope || obj, args)) !== undefined) {
                    if (typeof v == 'object') {
                        if (v.returnValue !== undefined) {
                            returnValue = v.returnValue;
                        } else {
                            returnValue = v;
                        }
                        cancel = !!v.cancel;
                    }
                    else
                        if (v === false) {
                            cancel = true;
                        }
                        else {
                            returnValue = v;
                        }
                }
            };

            this[method] = function () {
                var args = Array.prototype.slice.call(arguments, 0),
                    b;
                returnValue = v = undefined;
                cancel = false;

                for (var i = 0, len = e.before.length; i < len; i++) {
                    b = e.before[i];
                    makeCall(b.fn, b.scope, args);
                    if (cancel) {
                        return returnValue;
                    }
                }

                if ((v = e.originalFn.apply(obj, args)) !== undefined) {
                    returnValue = v;
                }

                for (var i = 0, len = e.after.length; i < len; i++) {
                    b = e.after[i];
                    makeCall(b.fn, b.scope, args);
                    if (cancel) {
                        return returnValue;
                    }
                }
                return returnValue;
            };
        }
        return e;
    }

    return {
        // these are considered experimental
        // allows for easier interceptor and sequences, including cancelling and overwriting the return value of the call
        // adds an 'interceptor' called before the original method
        beforeMethod: function (method, fn, scope) {
            getMethodEvent.call(this, method).before.push({
                fn: fn,
                scope: scope
            });
        },

        // adds a 'sequence' called after the original method
        afterMethod: function (method, fn, scope) {
            getMethodEvent.call(this, method).after.push({
                fn: fn,
                scope: scope
            });
        },

        removeMethodListener: function (method, fn, scope) {
            var e = this.getMethodEvent(method);
            for (var i = 0, len = e.before.length; i < len; i++) {
                if (e.before[i].fn == fn && e.before[i].scope == scope) {
                    e.before.splice(i, 1);
                    return;
                }
            }
            for (var i = 0, len = e.after.length; i < len; i++) {
                if (e.after[i].fn == fn && e.after[i].scope == scope) {
                    e.after.splice(i, 1);
                    return;
                }
            }
        },

        /**
        * Relays selected events from the specified Observable as if the events were fired by <tt><b>this</b></tt>.
        * @param {Object} o The Observable whose events this object is to relay.
        * @param {Array} events Array of event names to relay.
        */
        relayEvents: function (o, events) {
            var me = this;
            function createHandler(ename) {
                return function () {
                    return me.fireEvent.apply(me, [ename].concat(Array.prototype.slice.call(arguments, 0)));
                };
            }
            for (var i = 0, len = events.length; i < len; i++) {
                var ename = events[i];
                me.events[ename] = me.events[ename] || true;
                o.on(ename, createHandler(ename), me);
            }
        },

        /**
        * <p>Enables events fired by this Observable to bubble up an owner hierarchy by calling
        * <code>this.getBubbleTarget()</code> if present. There is no implementation in the Observable base class.</p>
        * <p>This is commonly used by Ext.Components to bubble events to owner Containers. See {@link Ext.Component.getBubbleTarget}. The default
        * implementation in Ext.Component returns the Component's immediate owner. But if a known target is required, this can be overridden to
        * access the required target more quickly.</p>
        * <p>Example:</p><pre><code>
        Ext.override(Ext.form.Field, {
    
        initComponent : Ext.form.Field.prototype.initComponent.createSequence(function() {
        this.enableBubble('change');
        }),

    
        getBubbleTarget : function() {
        if (!this.formPanel) {
        this.formPanel = this.findParentByType('form');
        }
        return this.formPanel;
        }
        });

        var myForm = new Ext.formPanel({
        title: 'User Details',
        items: [{
        ...
        }],
        listeners: {
        change: function() {
            
        myForm.header.setStyle('color', 'red');
        }
        }
        });
        </code></pre>
        * @param {String/Array} events The event name to bubble, or an Array of event names.
        */
        enableBubble: function (events) {
            var me = this;
            if (!Ext.isEmpty(events)) {
                events = Ext.isArray(events) ? events : Array.prototype.slice.call(arguments, 0);
                for (var i = 0, len = events.length; i < len; i++) {
                    var ename = events[i];
                    ename = ename.toLowerCase();
                    var ce = me.events[ename] || true;
                    if (typeof ce == 'boolean') {
                        ce = new Ext.util.Event(me, ename);
                        me.events[ename] = ce;
                    }
                    ce.bubble = true;
                }
            }
        }
    };
} ());



Ext.util.Observable.capture = function (o, fn, scope) {
    o.fireEvent = o.fireEvent.createInterceptor(fn, scope);
};



Ext.util.Observable.observeClass = function (c, listeners) {
    if (c) {
        if (!c.fireEvent) {
            Ext.apply(c, new Ext.util.Observable());
            Ext.util.Observable.capture(c.prototype, c.fireEvent, c);
        }
        if (typeof listeners == 'object') {
            c.on(listeners);
        }
        return c;
    }
};

Ext.apply(Ext.EventManager, function () {
    var resizeEvent,
       resizeTask,
       textEvent,
       textSize,
       D = Ext.lib.Dom,
       propRe = /^(?:scope|delay|buffer|single|stopEvent|preventDefault|stopPropagation|normalized|args|delegate)$/,
       curWidth = 0,
       curHeight = 0,



       useKeydown = Ext.isWebKit ?
                   Ext.num(navigator.userAgent.match(/AppleWebKit\/(\d+)/)[1]) >= 525 :
                   !((Ext.isGecko && !Ext.isWindows) || Ext.isOpera);

    return {

        doResizeEvent: function () {
            var h = D.getViewHeight(),
               w = D.getViewWidth();


            if (curHeight != h || curWidth != w) {
                resizeEvent.fire(curWidth = w, curHeight = h);
            }
        },


        onWindowResize: function (fn, scope, options) {
            if (!resizeEvent) {
                resizeEvent = new Ext.util.Event();
                resizeTask = new Ext.util.DelayedTask(this.doResizeEvent);
                Ext.EventManager.on(window, "resize", this.fireWindowResize, this);
            }
            resizeEvent.addListener(fn, scope, options);
        },


        fireWindowResize: function () {
            if (resizeEvent) {
                resizeTask.delay(100);
            }
        },


        onTextResize: function (fn, scope, options) {
            if (!textEvent) {
                textEvent = new Ext.util.Event();
                var textEl = new Ext.Element(document.createElement('div'));
                textEl.dom.className = 'x-text-resize';
                textEl.dom.innerHTML = 'X';
                textEl.appendTo(document.body);
                textSize = textEl.dom.offsetHeight;
                setInterval(function () {
                    if (textEl.dom.offsetHeight != textSize) {
                        textEvent.fire(textSize, textSize = textEl.dom.offsetHeight);
                    }
                }, this.textResizeInterval);
            }
            textEvent.addListener(fn, scope, options);
        },


        removeResizeListener: function (fn, scope) {
            if (resizeEvent) {
                resizeEvent.removeListener(fn, scope);
            }
        },


        fireResize: function () {
            if (resizeEvent) {
                resizeEvent.fire(D.getViewWidth(), D.getViewHeight());
            }
        },


        textResizeInterval: 50,


        ieDeferSrc: false,


        getKeyEvent: function () {
            return useKeydown ? 'keydown' : 'keypress';
        },



        useKeydown: useKeydown
    };
} ());

Ext.EventManager.on = Ext.EventManager.addListener;


Ext.apply(Ext.EventObjectImpl.prototype, {

    BACKSPACE: 8,

    TAB: 9,

    NUM_CENTER: 12,

    ENTER: 13,

    RETURN: 13,

    SHIFT: 16,

    CTRL: 17,
    CONTROL: 17,

    ALT: 18,

    PAUSE: 19,

    CAPS_LOCK: 20,

    ESC: 27,

    SPACE: 32,

    PAGE_UP: 33,
    PAGEUP: 33,

    PAGE_DOWN: 34,
    PAGEDOWN: 34,

    END: 35,

    HOME: 36,

    LEFT: 37,

    UP: 38,

    RIGHT: 39,

    DOWN: 40,

    PRINT_SCREEN: 44,

    INSERT: 45,

    DELETE: 46,

    ZERO: 48,

    ONE: 49,

    TWO: 50,

    THREE: 51,

    FOUR: 52,

    FIVE: 53,

    SIX: 54,

    SEVEN: 55,

    EIGHT: 56,

    NINE: 57,

    A: 65,

    B: 66,

    C: 67,

    D: 68,

    E: 69,

    F: 70,

    G: 71,

    H: 72,

    I: 73,

    J: 74,

    K: 75,

    L: 76,

    M: 77,

    N: 78,

    O: 79,

    P: 80,

    Q: 81,

    R: 82,

    S: 83,

    T: 84,

    U: 85,

    V: 86,

    W: 87,

    X: 88,

    Y: 89,

    Z: 90,

    CONTEXT_MENU: 93,

    NUM_ZERO: 96,

    NUM_ONE: 97,

    NUM_TWO: 98,

    NUM_THREE: 99,

    NUM_FOUR: 100,

    NUM_FIVE: 101,

    NUM_SIX: 102,

    NUM_SEVEN: 103,

    NUM_EIGHT: 104,

    NUM_NINE: 105,

    NUM_MULTIPLY: 106,

    NUM_PLUS: 107,

    NUM_MINUS: 109,

    NUM_PERIOD: 110,

    NUM_DIVISION: 111,

    F1: 112,

    F2: 113,

    F3: 114,

    F4: 115,

    F5: 116,

    F6: 117,

    F7: 118,

    F8: 119,

    F9: 120,

    F10: 121,

    F11: 122,

    F12: 123,


    isNavKeyPress: function () {
        var me = this,
           k = this.normalizeKey(me.keyCode);
        return (k >= 33 && k <= 40) ||
       k == me.RETURN ||
       k == me.TAB ||
       k == me.ESC;
    },

    isSpecialKey: function () {
        var k = this.normalizeKey(this.keyCode);
        return (this.type == 'keypress' && this.ctrlKey) ||
       this.isNavKeyPress() ||
       (k == this.BACKSPACE) ||
       (k >= 16 && k <= 20) ||
       (k >= 44 && k <= 46);
    },

    getPoint: function () {
        return new Ext.lib.Point(this.xy[0], this.xy[1]);
    },


    hasModifier: function () {
        return ((this.ctrlKey || this.altKey) || this.shiftKey);
    }
});
Ext.Element.addMethods({

    swallowEvent: function (eventName, preventDefault) {
        var me = this;
        function fn(e) {
            e.stopPropagation();
            if (preventDefault) {
                e.preventDefault();
            }
        }

        if (Ext.isArray(eventName)) {
            Ext.each(eventName, function (e) {
                me.on(e, fn);
            });
            return me;
        }
        me.on(eventName, fn);
        return me;
    },


    relayEvent: function (eventName, observable) {
        this.on(eventName, function (e) {
            observable.fireEvent(eventName, e);
        });
    },


    clean: function (forceReclean) {
        var me = this,
            dom = me.dom,
            n = dom.firstChild,
            ni = -1;

        if (Ext.Element.data(dom, 'isCleaned') && forceReclean !== true) {
            return me;
        }

        while (n) {
            var nx = n.nextSibling;
            if (n.nodeType == 3 && !(/\S/.test(n.nodeValue))) {
                dom.removeChild(n);
            } else {
                n.nodeIndex = ++ni;
            }
            n = nx;
        }

        Ext.Element.data(dom, 'isCleaned', true);
        return me;
    },


    load: function () {
        var updateManager = this.getUpdater();
        updateManager.update.apply(updateManager, arguments);

        return this;
    },


    getUpdater: function () {
        return this.updateManager || (this.updateManager = new Ext.Updater(this));
    },


    update: function (html, loadScripts, callback) {
        if (!this.dom) {
            return this;
        }
        html = html || "";

        if (loadScripts !== true) {
            this.dom.innerHTML = html;
            if (typeof callback == 'function') {
                callback();
            }
            return this;
        }

        var id = Ext.id(),
            dom = this.dom;

        html += '<span id="' + id + '"></span>';

        Ext.lib.Event.onAvailable(id, function () {
            var DOC = document,
                hd = DOC.getElementsByTagName("head")[0],
                re = /(?:<script([^>]*)?>)((\n|\r|.)*?)(?:<\/script>)/ig,
                srcRe = /\ssrc=([\'\"])(.*?)\1/i,
                typeRe = /\stype=([\'\"])(.*?)\1/i,
                match,
                attrs,
                srcMatch,
                typeMatch,
                el,
                s;

            while ((match = re.exec(html))) {
                attrs = match[1];
                srcMatch = attrs ? attrs.match(srcRe) : false;
                if (srcMatch && srcMatch[2]) {
                    s = DOC.createElement("script");
                    s.src = srcMatch[2];
                    typeMatch = attrs.match(typeRe);
                    if (typeMatch && typeMatch[2]) {
                        s.type = typeMatch[2];
                    }
                    hd.appendChild(s);
                } else if (match[2] && match[2].length > 0) {
                    if (window.execScript) {
                        window.execScript(match[2]);
                    } else {
                        window.eval(match[2]);
                    }
                }
            }

            el = DOC.getElementById(id);
            if (el) {
                Ext.removeNode(el);
            }

            if (typeof callback == 'function') {
                callback();
            }
        });
        dom.innerHTML = html.replace(/(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)/ig, "");
        return this;
    },


    removeAllListeners: function () {
        this.removeAnchor();
        Ext.EventManager.removeAll(this.dom);
        return this;
    },


    createProxy: function (config, renderTo, matchBox) {
        config = (typeof config == 'object') ? config : { tag: "div", cls: config };

        var me = this,
            proxy = renderTo ? Ext.DomHelper.append(renderTo, config, true) :
                               Ext.DomHelper.insertBefore(me.dom, config, true);

        if (matchBox && me.setBox && me.getBox) {
            proxy.setBox(me.getBox());
        }
        return proxy;
    }
});

Ext.Element.prototype.getUpdateManager = Ext.Element.prototype.getUpdater;

Ext.Element.addMethods({

    getAnchorXY: function (anchor, local, s) {


        anchor = (anchor || "tl").toLowerCase();
        s = s || {};

        var me = this,
        	vp = me.dom == document.body || me.dom == document,
        	w = s.width || vp ? Ext.lib.Dom.getViewWidth() : me.getWidth(),
        	h = s.height || vp ? Ext.lib.Dom.getViewHeight() : me.getHeight(),
        	xy,
        	r = Math.round,
        	o = me.getXY(),
        	scroll = me.getScroll(),
        	extraX = vp ? scroll.left : !local ? o[0] : 0,
        	extraY = vp ? scroll.top : !local ? o[1] : 0,
        	hash = {
        	    c: [r(w * 0.5), r(h * 0.5)],
        	    t: [r(w * 0.5), 0],
        	    l: [0, r(h * 0.5)],
        	    r: [w, r(h * 0.5)],
        	    b: [r(w * 0.5), h],
        	    tl: [0, 0],
        	    bl: [0, h],
        	    br: [w, h],
        	    tr: [w, 0]
        	};

        xy = hash[anchor];
        return [xy[0] + extraX, xy[1] + extraY];
    },


    anchorTo: function (el, alignment, offsets, animate, monitorScroll, callback) {
        var me = this,
            dom = me.dom,
            scroll = !Ext.isEmpty(monitorScroll),
            action = function () {
                Ext.fly(dom).alignTo(el, alignment, offsets, animate);
                Ext.callback(callback, Ext.fly(dom));
            },
            anchor = this.getAnchor();


        this.removeAnchor();
        Ext.apply(anchor, {
            fn: action,
            scroll: scroll
        });

        Ext.EventManager.onWindowResize(action, null);

        if (scroll) {
            Ext.EventManager.on(window, 'scroll', action, null,
                { buffer: !isNaN(monitorScroll) ? monitorScroll : 50 });
        }
        action.call(me);
        return me;
    },


    removeAnchor: function () {
        var me = this,
            anchor = this.getAnchor();

        if (anchor && anchor.fn) {
            Ext.EventManager.removeResizeListener(anchor.fn);
            if (anchor.scroll) {
                Ext.EventManager.un(window, 'scroll', anchor.fn);
            }
            delete anchor.fn;
        }
        return me;
    },


    getAnchor: function () {
        var data = Ext.Element.data,
            dom = this.dom;
        if (!dom) {
            return;
        }
        var anchor = data(dom, '_anchor');

        if (!anchor) {
            anchor = data(dom, '_anchor', {});
        }
        return anchor;
    },


    getAlignToXY: function (el, p, o) {
        el = Ext.get(el);

        if (!el || !el.dom) {
            throw "Element.alignToXY with an element that doesn't exist";
        }

        o = o || [0, 0];
        p = (!p || p == "?" ? "tl-bl?" : (!(/-/).test(p) && p !== "" ? "tl-" + p : p || "tl-bl")).toLowerCase();

        var me = this,
        	d = me.dom,
        	a1,
        	a2,
        	x,
        	y,

        	w,
        	h,
        	r,
        	dw = Ext.lib.Dom.getViewWidth() - 10,
        	dh = Ext.lib.Dom.getViewHeight() - 10,
        	p1y,
        	p1x,
        	p2y,
        	p2x,
        	swapY,
        	swapX,
        	doc = document,
        	docElement = doc.documentElement,
        	docBody = doc.body,
        	scrollX = (docElement.scrollLeft || docBody.scrollLeft || 0) + 5,
        	scrollY = (docElement.scrollTop || docBody.scrollTop || 0) + 5,
        	c = false,
        	p1 = "",
        	p2 = "",
        	m = p.match(/^([a-z]+)-([a-z]+)(\?)?$/);

        if (!m) {
            throw "Element.alignTo with an invalid alignment " + p;
        }

        p1 = m[1];
        p2 = m[2];
        c = !!m[3];



        a1 = me.getAnchorXY(p1, true);
        a2 = el.getAnchorXY(p2, false);

        x = a2[0] - a1[0] + o[0];
        y = a2[1] - a1[1] + o[1];

        if (c) {
            w = me.getWidth();
            h = me.getHeight();
            r = el.getRegion();



            p1y = p1.charAt(0);
            p1x = p1.charAt(p1.length - 1);
            p2y = p2.charAt(0);
            p2x = p2.charAt(p2.length - 1);
            swapY = ((p1y == "t" && p2y == "b") || (p1y == "b" && p2y == "t"));
            swapX = ((p1x == "r" && p2x == "l") || (p1x == "l" && p2x == "r"));


            if (x + w > dw + scrollX) {
                x = swapX ? r.left - w : dw + scrollX - w;
            }
            if (x < scrollX) {
                x = swapX ? r.right : scrollX;
            }
            if (y + h > dh + scrollY) {
                y = swapY ? r.top - h : dh + scrollY - h;
            }
            if (y < scrollY) {
                y = swapY ? r.bottom : scrollY;
            }
        }
        return [x, y];
    },


    alignTo: function (element, position, offsets, animate) {
        var me = this;
        return me.setXY(me.getAlignToXY(element, position, offsets),
          		        me.preanim && !!animate ? me.preanim(arguments, 3) : false);
    },


    adjustForConstraints: function (xy, parent, offsets) {
        return this.getConstrainToXY(parent || document, false, offsets, xy) || xy;
    },


    getConstrainToXY: function (el, local, offsets, proposedXY) {
        var os = { top: 0, left: 0, bottom: 0, right: 0 };

        return function (el, local, offsets, proposedXY) {
            el = Ext.get(el);
            offsets = offsets ? Ext.applyIf(offsets, os) : os;

            var vw, vh, vx = 0, vy = 0;
            if (el.dom == document.body || el.dom == document) {
                vw = Ext.lib.Dom.getViewWidth();
                vh = Ext.lib.Dom.getViewHeight();
            } else {
                vw = el.dom.clientWidth;
                vh = el.dom.clientHeight;
                if (!local) {
                    var vxy = el.getXY();
                    vx = vxy[0];
                    vy = vxy[1];
                }
            }

            var s = el.getScroll();

            vx += offsets.left + s.left;
            vy += offsets.top + s.top;

            vw -= offsets.right;
            vh -= offsets.bottom;

            var vr = vx + vw,
                vb = vy + vh,
                xy = proposedXY || (!local ? this.getXY() : [this.getLeft(true), this.getTop(true)]),
                x = xy[0], y = xy[1],
                offset = this.getConstrainOffset(),
                w = this.dom.offsetWidth + offset,
                h = this.dom.offsetHeight + offset;


            var moved = false;


            if ((x + w) > vr) {
                x = vr - w;
                moved = true;
            }
            if ((y + h) > vb) {
                y = vb - h;
                moved = true;
            }

            if (x < vx) {
                x = vx;
                moved = true;
            }
            if (y < vy) {
                y = vy;
                moved = true;
            }
            return moved ? [x, y] : false;
        };
    } (),

























































    getConstrainOffset: function () {
        return 0;
    },


    getCenterXY: function () {
        return this.getAlignToXY(document, 'c-c');
    },


    center: function (centerIn) {
        return this.alignTo(centerIn || document, 'c-c');
    }
});

Ext.Element.addMethods({

    select: function (selector, unique) {
        return Ext.Element.select(selector, unique, this.dom);
    }
});
Ext.apply(Ext.Element.prototype, function () {
    var GETDOM = Ext.getDom,
		GET = Ext.get,
		DH = Ext.DomHelper;

    return {

        insertSibling: function (el, where, returnDom) {
            var me = this,
	        	rt,
                isAfter = (where || 'before').toLowerCase() == 'after',
                insertEl;

            if (Ext.isArray(el)) {
                insertEl = me;
                Ext.each(el, function (e) {
                    rt = Ext.fly(insertEl, '_internal').insertSibling(e, where, returnDom);
                    if (isAfter) {
                        insertEl = rt;
                    }
                });
                return rt;
            }

            el = el || {};

            if (el.nodeType || el.dom) {
                rt = me.dom.parentNode.insertBefore(GETDOM(el), isAfter ? me.dom.nextSibling : me.dom);
                if (!returnDom) {
                    rt = GET(rt);
                }
            } else {
                if (isAfter && !me.dom.nextSibling) {
                    rt = DH.append(me.dom.parentNode, el, !returnDom);
                } else {
                    rt = DH[isAfter ? 'insertAfter' : 'insertBefore'](me.dom, el, !returnDom);
                }
            }
            return rt;
        }
    };
} ());


Ext.Element.boxMarkup = '<div class="{0}-tl"><div class="{0}-tr"><div class="{0}-tc"></div></div></div><div class="{0}-ml"><div class="{0}-mr"><div class="{0}-mc"></div></div></div><div class="{0}-bl"><div class="{0}-br"><div class="{0}-bc"></div></div></div>';

Ext.Element.addMethods(function () {
    var INTERNAL = "_internal",
        pxMatch = /(\d+\.?\d+)px/;
    return {

        applyStyles: function (style) {
            Ext.DomHelper.applyStyles(this.dom, style);
            return this;
        },


        getStyles: function () {
            var ret = {};
            Ext.each(arguments, function (v) {
                ret[v] = this.getStyle(v);
            },
            this);
            return ret;
        },


        setOverflow: function (v) {
            var dom = this.dom;
            if (v == 'auto' && Ext.isMac && Ext.isGecko2) {
                dom.style.overflow = 'hidden';
                (function () { dom.style.overflow = 'auto'; }).defer(1);
            } else {
                dom.style.overflow = v;
            }
        },


        boxWrap: function (cls) {
            cls = cls || 'x-box';
            var el = Ext.get(this.insertHtml("beforeBegin", "<div class='" + cls + "'>" + String.format(Ext.Element.boxMarkup, cls) + "</div>"));
            Ext.DomQuery.selectNode('.' + cls + '-mc', el.dom).appendChild(this.dom);
            return el;
        },


        setSize: function (width, height, animate) {
            var me = this;
            if (typeof width == 'object') {
                height = width.height;
                width = width.width;
            }
            width = me.adjustWidth(width);
            height = me.adjustHeight(height);
            if (!animate || !me.anim) {
                me.dom.style.width = me.addUnits(width);
                me.dom.style.height = me.addUnits(height);
            } else {
                me.anim({ width: { to: width }, height: { to: height} }, me.preanim(arguments, 2));
            }
            return me;
        },


        getComputedHeight: function () {
            var me = this,
                h = Math.max(me.dom.offsetHeight, me.dom.clientHeight);
            if (!h) {
                h = parseFloat(me.getStyle('height')) || 0;
                if (!me.isBorderBox()) {
                    h += me.getFrameWidth('tb');
                }
            }
            return h;
        },


        getComputedWidth: function () {
            var w = Math.max(this.dom.offsetWidth, this.dom.clientWidth);
            if (!w) {
                w = parseFloat(this.getStyle('width')) || 0;
                if (!this.isBorderBox()) {
                    w += this.getFrameWidth('lr');
                }
            }
            return w;
        },


        getFrameWidth: function (sides, onlyContentBox) {
            return onlyContentBox && this.isBorderBox() ? 0 : (this.getPadding(sides) + this.getBorderWidth(sides));
        },


        addClassOnOver: function (className) {
            this.hover(
                function () {
                    Ext.fly(this, INTERNAL).addClass(className);
                },
                function () {
                    Ext.fly(this, INTERNAL).removeClass(className);
                }
            );
            return this;
        },


        addClassOnFocus: function (className) {
            this.on("focus", function () {
                Ext.fly(this, INTERNAL).addClass(className);
            }, this.dom);
            this.on("blur", function () {
                Ext.fly(this, INTERNAL).removeClass(className);
            }, this.dom);
            return this;
        },


        addClassOnClick: function (className) {
            var dom = this.dom;
            this.on("mousedown", function () {
                Ext.fly(dom, INTERNAL).addClass(className);
                var d = Ext.getDoc(),
                    fn = function () {
                        Ext.fly(dom, INTERNAL).removeClass(className);
                        d.removeListener("mouseup", fn);
                    };
                d.on("mouseup", fn);
            });
            return this;
        },



        getViewSize: function () {
            var doc = document,
                d = this.dom,
                isDoc = (d == doc || d == doc.body);


            if (isDoc) {
                var extdom = Ext.lib.Dom;
                return {
                    width: extdom.getViewWidth(),
                    height: extdom.getViewHeight()
                };


            } else {
                return {
                    width: d.clientWidth,
                    height: d.clientHeight
                };
            }
        },



        getStyleSize: function () {
            var me = this,
                w, h,
                doc = document,
                d = this.dom,
                isDoc = (d == doc || d == doc.body),
                s = d.style;


            if (isDoc) {
                var extdom = Ext.lib.Dom;
                return {
                    width: extdom.getViewWidth(),
                    height: extdom.getViewHeight()
                };
            }

            if (s.width && s.width != 'auto') {
                w = parseFloat(s.width);
                if (me.isBorderBox()) {
                    w -= me.getFrameWidth('lr');
                }
            }

            if (s.height && s.height != 'auto') {
                h = parseFloat(s.height);
                if (me.isBorderBox()) {
                    h -= me.getFrameWidth('tb');
                }
            }

            return { width: w || me.getWidth(true), height: h || me.getHeight(true) };
        },


        getSize: function (contentSize) {
            return { width: this.getWidth(contentSize), height: this.getHeight(contentSize) };
        },


        repaint: function () {
            var dom = this.dom;
            this.addClass("x-repaint");
            setTimeout(function () {
                Ext.fly(dom).removeClass("x-repaint");
            }, 1);
            return this;
        },


        unselectable: function () {
            this.dom.unselectable = "on";
            return this.swallowEvent("selectstart", true).
                        applyStyles("-moz-user-select:none;-khtml-user-select:none;").
                        addClass("x-unselectable");
        },


        getMargins: function (side) {
            var me = this,
                key,
                hash = { t: "top", l: "left", r: "right", b: "bottom" },
                o = {};

            if (!side) {
                for (key in me.margins) {
                    o[hash[key]] = parseFloat(me.getStyle(me.margins[key])) || 0;
                }
                return o;
            } else {
                return me.addStyles.call(me, side, me.margins);
            }
        }
    };
} ());

Ext.Element.addMethods({

    setBox: function (box, adjust, animate) {
        var me = this,
        	w = box.width,
        	h = box.height;
        if ((adjust && !me.autoBoxAdjust) && !me.isBorderBox()) {
            w -= (me.getBorderWidth("lr") + me.getPadding("lr"));
            h -= (me.getBorderWidth("tb") + me.getPadding("tb"));
        }
        me.setBounds(box.x, box.y, w, h, me.animTest.call(me, arguments, animate, 2));
        return me;
    },


    getBox: function (contentBox, local) {
        var me = this,
        	xy,
        	left,
        	top,
        	getBorderWidth = me.getBorderWidth,
        	getPadding = me.getPadding,
        	l,
        	r,
        	t,
        	b;
        if (!local) {
            xy = me.getXY();
        } else {
            left = parseInt(me.getStyle("left"), 10) || 0;
            top = parseInt(me.getStyle("top"), 10) || 0;
            xy = [left, top];
        }
        var el = me.dom, w = el.offsetWidth, h = el.offsetHeight, bx;
        if (!contentBox) {
            bx = { x: xy[0], y: xy[1], 0: xy[0], 1: xy[1], width: w, height: h };
        } else {
            l = getBorderWidth.call(me, "l") + getPadding.call(me, "l");
            r = getBorderWidth.call(me, "r") + getPadding.call(me, "r");
            t = getBorderWidth.call(me, "t") + getPadding.call(me, "t");
            b = getBorderWidth.call(me, "b") + getPadding.call(me, "b");
            bx = { x: xy[0] + l, y: xy[1] + t, 0: xy[0] + l, 1: xy[1] + t, width: w - (l + r), height: h - (t + b) };
        }
        bx.right = bx.x + bx.width;
        bx.bottom = bx.y + bx.height;
        return bx;
    },


    move: function (direction, distance, animate) {
        var me = this,
        	xy = me.getXY(),
        	x = xy[0],
        	y = xy[1],
        	left = [x - distance, y],
        	right = [x + distance, y],
        	top = [x, y - distance],
        	bottom = [x, y + distance],
	       	hash = {
	       	    l: left,
	       	    left: left,
	       	    r: right,
	       	    right: right,
	       	    t: top,
	       	    top: top,
	       	    up: top,
	       	    b: bottom,
	       	    bottom: bottom,
	       	    down: bottom
	       	};

        direction = direction.toLowerCase();
        me.moveTo(hash[direction][0], hash[direction][1], me.animTest.call(me, arguments, animate, 2));
    },


    setLeftTop: function (left, top) {
        var me = this,
	    	style = me.dom.style;
        style.left = me.addUnits(left);
        style.top = me.addUnits(top);
        return me;
    },


    getRegion: function () {
        return Ext.lib.Dom.getRegion(this.dom);
    },


    setBounds: function (x, y, width, height, animate) {
        var me = this;
        if (!animate || !me.anim) {
            me.setSize(width, height);
            me.setLocation(x, y);
        } else {
            me.anim({ points: { to: [x, y] },
                width: { to: me.adjustWidth(width) },
                height: { to: me.adjustHeight(height)}
            },
                     me.preanim(arguments, 4),
                     'motion');
        }
        return me;
    },


    setRegion: function (region, animate) {
        return this.setBounds(region.left, region.top, region.right - region.left, region.bottom - region.top, this.animTest.call(this, arguments, animate, 1));
    }
});
Ext.Element.addMethods({

    scrollTo: function (side, value, animate) {

        var top = /top/i.test(side),
            me = this,
            dom = me.dom,
            prop;
        if (!animate || !me.anim) {

            prop = 'scroll' + (top ? 'Top' : 'Left');
            dom[prop] = value;
        }
        else {

            prop = 'scroll' + (top ? 'Left' : 'Top');
            me.anim({ scroll: { to: top ? [dom[prop], value] : [value, dom[prop]]} }, me.preanim(arguments, 2), 'scroll');
        }
        return me;
    },


    scrollIntoView: function (container, hscroll) {
        var c = Ext.getDom(container) || Ext.getBody().dom,
            el = this.dom,
            o = this.getOffsetsTo(c),
            l = o[0] + c.scrollLeft,
            t = o[1] + c.scrollTop,
            b = t + el.offsetHeight,
            r = l + el.offsetWidth,
            ch = c.clientHeight,
            ct = parseInt(c.scrollTop, 10),
            cl = parseInt(c.scrollLeft, 10),
            cb = ct + ch,
            cr = cl + c.clientWidth;

        if (el.offsetHeight > ch || t < ct) {
            c.scrollTop = t;
        }
        else if (b > cb) {
            c.scrollTop = b - ch;
        }

        c.scrollTop = c.scrollTop;

        if (hscroll !== false) {
            if (el.offsetWidth > c.clientWidth || l < cl) {
                c.scrollLeft = l;
            }
            else if (r > cr) {
                c.scrollLeft = r - c.clientWidth;
            }
            c.scrollLeft = c.scrollLeft;
        }
        return this;
    },


    scrollChildIntoView: function (child, hscroll) {
        Ext.fly(child, '_scrollChildIntoView').scrollIntoView(this, hscroll);
    },


    scroll: function (direction, distance, animate) {
        if (!this.isScrollable()) {
            return false;
        }
        var el = this.dom,
            l = el.scrollLeft, t = el.scrollTop,
            w = el.scrollWidth, h = el.scrollHeight,
            cw = el.clientWidth, ch = el.clientHeight,
            scrolled = false, v,
            hash = {
                l: Math.min(l + distance, w - cw),
                r: v = Math.max(l - distance, 0),
                t: Math.max(t - distance, 0),
                b: Math.min(t + distance, h - ch)
            };
        hash.d = hash.b;
        hash.u = hash.t;

        direction = direction.substr(0, 1);
        if ((v = hash[direction]) > -1) {
            scrolled = true;
            this.scrollTo(direction == 'l' || direction == 'r' ? 'left' : 'top', v, this.preanim(arguments, 2));
        }
        return scrolled;
    }
});
Ext.Element.addMethods(
    function () {
        var VISIBILITY = "visibility",
            DISPLAY = "display",
            HIDDEN = "hidden",
            NONE = "none",
            XMASKED = "x-masked",
            XMASKEDRELATIVE = "x-masked-relative",
            data = Ext.Element.data;

        return {

            isVisible: function (deep) {
                var vis = !this.isStyle(VISIBILITY, HIDDEN) && !this.isStyle(DISPLAY, NONE),
                    p = this.dom.parentNode;

                if (deep !== true || !vis) {
                    return vis;
                }

                while (p && !(/^body/i.test(p.tagName))) {
                    if (!Ext.fly(p, '_isVisible').isVisible()) {
                        return false;
                    }
                    p = p.parentNode;
                }
                return true;
            },


            isDisplayed: function () {
                return !this.isStyle(DISPLAY, NONE);
            },


            enableDisplayMode: function (display) {
                this.setVisibilityMode(Ext.Element.DISPLAY);

                if (!Ext.isEmpty(display)) {
                    data(this.dom, 'originalDisplay', display);
                }

                return this;
            },


            mask: function (msg, msgCls) {
                var me = this,
                    dom = me.dom,
                    dh = Ext.DomHelper,
                    EXTELMASKMSG = "ext-el-mask-msg",
                    el,
                    mask;

                if (!(/^body/i.test(dom.tagName) && me.getStyle('position') == 'static')) {
                    me.addClass(XMASKEDRELATIVE);
                }
                if (el = data(dom, 'maskMsg')) {
                    el.remove();
                }
                if (el = data(dom, 'mask')) {
                    el.remove();
                }

                mask = dh.append(dom, { cls: "ext-el-mask" }, true);
                data(dom, 'mask', mask);

                me.addClass(XMASKED);
                mask.setDisplayed(true);

                if (typeof msg == 'string') {
                    var mm = dh.append(dom, { cls: EXTELMASKMSG, cn: { tag: 'div'} }, true);
                    data(dom, 'maskMsg', mm);
                    mm.dom.className = msgCls ? EXTELMASKMSG + " " + msgCls : EXTELMASKMSG;
                    mm.dom.firstChild.innerHTML = msg;
                    mm.setDisplayed(true);
                    mm.center(me);
                }


                if (Ext.isIE && !(Ext.isIE7 && Ext.isStrict) && me.getStyle('height') == 'auto') {
                    mask.setSize(undefined, me.getHeight());
                }

                return mask;
            },


            unmask: function () {
                var me = this,
                    dom = me.dom,
                    mask = data(dom, 'mask'),
                    maskMsg = data(dom, 'maskMsg');

                if (mask) {
                    if (maskMsg) {
                        maskMsg.remove();
                        data(dom, 'maskMsg', undefined);
                    }

                    mask.remove();
                    data(dom, 'mask', undefined);
                    me.removeClass([XMASKED, XMASKEDRELATIVE]);
                }
            },


            isMasked: function () {
                var m = data(this.dom, 'mask');
                return m && m.isVisible();
            },


            createShim: function () {
                var el = document.createElement('iframe'),
                    shim;

                el.frameBorder = '0';
                el.className = 'ext-shim';
                el.src = Ext.SSL_SECURE_URL;
                shim = Ext.get(this.dom.parentNode.insertBefore(el, this.dom));
                shim.autoBoxAdjust = false;
                return shim;
            }
        };
    } ()
);
Ext.Element.addMethods({

    addKeyListener: function (key, fn, scope) {
        var config;
        if (typeof key != 'object' || Ext.isArray(key)) {
            config = {
                key: key,
                fn: fn,
                scope: scope
            };
        } else {
            config = {
                key: key.key,
                shift: key.shift,
                ctrl: key.ctrl,
                alt: key.alt,
                fn: fn,
                scope: scope
            };
        }
        return new Ext.KeyMap(this, config);
    },


    addKeyMap: function (config) {
        return new Ext.KeyMap(this, config);
    }
});



Ext.CompositeElementLite.importElementMethods();
Ext.apply(Ext.CompositeElementLite.prototype, {
    addElements: function (els, root) {
        if (!els) {
            return this;
        }
        if (typeof els == "string") {
            els = Ext.Element.selectorFunction(els, root);
        }
        var yels = this.elements;
        Ext.each(els, function (e) {
            yels.push(Ext.get(e));
        });
        return this;
    },


    first: function () {
        return this.item(0);
    },


    last: function () {
        return this.item(this.getCount() - 1);
    },


    contains: function (el) {
        return this.indexOf(el) != -1;
    },


    removeElement: function (keys, removeDom) {
        var me = this,
            els = this.elements,
            el;
        Ext.each(keys, function (val) {
            if ((el = (els[val] || els[val = me.indexOf(val)]))) {
                if (removeDom) {
                    if (el.dom) {
                        el.remove();
                    } else {
                        Ext.removeNode(el);
                    }
                }
                els.splice(val, 1);
            }
        });
        return this;
    }
});

Ext.CompositeElement = Ext.extend(Ext.CompositeElementLite, {

    constructor: function (els, root) {
        this.elements = [];
        this.add(els, root);
    },


    getElement: function (el) {

        return el;
    },


    transformElement: function (el) {
        return Ext.get(el);
    }






});


Ext.Element.select = function (selector, unique, root) {
    var els;
    if (typeof selector == "string") {
        els = Ext.Element.selectorFunction(selector, root);
    } else if (selector.length !== undefined) {
        els = selector;
    } else {
        throw "Invalid selector";
    }

    return (unique === true) ? new Ext.CompositeElement(els) : new Ext.CompositeElementLite(els);
};


Ext.select = Ext.Element.select;
Ext.UpdateManager = Ext.Updater = Ext.extend(Ext.util.Observable,
function () {
    var BEFOREUPDATE = "beforeupdate",
        UPDATE = "update",
        FAILURE = "failure";


    function processSuccess(response) {
        var me = this;
        me.transaction = null;
        if (response.argument.form && response.argument.reset) {
            try {
                response.argument.form.reset();
            } catch (e) { }
        }
        if (me.loadScripts) {
            me.renderer.render(me.el, response, me,
               updateComplete.createDelegate(me, [response]));
        } else {
            me.renderer.render(me.el, response, me);
            updateComplete.call(me, response);
        }
    }


    function updateComplete(response, type, success) {
        this.fireEvent(type || UPDATE, this.el, response);
        if (Ext.isFunction(response.argument.callback)) {
            response.argument.callback.call(response.argument.scope, this.el, Ext.isEmpty(success) ? true : false, response, response.argument.options);
        }
    }


    function processFailure(response) {
        updateComplete.call(this, response, FAILURE, !!(this.transaction = null));
    }

    return {
        constructor: function (el, forceNew) {
            var me = this;
            el = Ext.get(el);
            if (!forceNew && el.updateManager) {
                return el.updateManager;
            }

            me.el = el;

            me.defaultUrl = null;

            me.addEvents(

                BEFOREUPDATE,

                UPDATE,

                FAILURE
            );

            Ext.apply(me, Ext.Updater.defaults);








            me.transaction = null;

            me.refreshDelegate = me.refresh.createDelegate(me);

            me.updateDelegate = me.update.createDelegate(me);

            me.formUpdateDelegate = (me.formUpdate || function () { }).createDelegate(me);


            me.renderer = me.renderer || me.getDefaultRenderer();

            Ext.Updater.superclass.constructor.call(me);
        },


        setRenderer: function (renderer) {
            this.renderer = renderer;
        },


        getRenderer: function () {
            return this.renderer;
        },


        getDefaultRenderer: function () {
            return new Ext.Updater.BasicRenderer();
        },


        setDefaultUrl: function (defaultUrl) {
            this.defaultUrl = defaultUrl;
        },


        getEl: function () {
            return this.el;
        },


        update: function (url, params, callback, discardUrl) {
            var me = this,
                cfg,
                callerScope;

            if (me.fireEvent(BEFOREUPDATE, me.el, url, params) !== false) {
                if (Ext.isObject(url)) {
                    cfg = url;
                    url = cfg.url;
                    params = params || cfg.params;
                    callback = callback || cfg.callback;
                    discardUrl = discardUrl || cfg.discardUrl;
                    callerScope = cfg.scope;
                    if (!Ext.isEmpty(cfg.nocache)) { me.disableCaching = cfg.nocache; };
                    if (!Ext.isEmpty(cfg.text)) { me.indicatorText = '<div class="loading-indicator">' + cfg.text + "</div>"; };
                    if (!Ext.isEmpty(cfg.scripts)) { me.loadScripts = cfg.scripts; };
                    if (!Ext.isEmpty(cfg.timeout)) { me.timeout = cfg.timeout; };
                }
                me.showLoading();

                if (!discardUrl) {
                    me.defaultUrl = url;
                }
                if (Ext.isFunction(url)) {
                    url = url.call(me);
                }

                var o = Ext.apply({}, {
                    url: url,
                    params: (Ext.isFunction(params) && callerScope) ? params.createDelegate(callerScope) : params,
                    success: processSuccess,
                    failure: processFailure,
                    scope: me,
                    callback: undefined,
                    timeout: (me.timeout * 1000),
                    disableCaching: me.disableCaching,
                    argument: {
                        "options": cfg,
                        "url": url,
                        "form": null,
                        "callback": callback,
                        "scope": callerScope || window,
                        "params": params
                    }
                }, cfg);

                me.transaction = Ext.Ajax.request(o);
            }
        },


        formUpdate: function (form, url, reset, callback) {
            var me = this;
            if (me.fireEvent(BEFOREUPDATE, me.el, form, url) !== false) {
                if (Ext.isFunction(url)) {
                    url = url.call(me);
                }
                form = Ext.getDom(form);
                me.transaction = Ext.Ajax.request({
                    form: form,
                    url: url,
                    success: processSuccess,
                    failure: processFailure,
                    scope: me,
                    timeout: (me.timeout * 1000),
                    argument: {
                        "url": url,
                        "form": form,
                        "callback": callback,
                        "reset": reset
                    }
                });
                me.showLoading.defer(1, me);
            }
        },


        startAutoRefresh: function (interval, url, params, callback, refreshNow) {
            var me = this;
            if (refreshNow) {
                me.update(url || me.defaultUrl, params, callback, true);
            }
            if (me.autoRefreshProcId) {
                clearInterval(me.autoRefreshProcId);
            }
            me.autoRefreshProcId = setInterval(me.update.createDelegate(me, [url || me.defaultUrl, params, callback, true]), interval * 1000);
        },


        stopAutoRefresh: function () {
            if (this.autoRefreshProcId) {
                clearInterval(this.autoRefreshProcId);
                delete this.autoRefreshProcId;
            }
        },


        isAutoRefreshing: function () {
            return !!this.autoRefreshProcId;
        },


        showLoading: function () {
            if (this.showLoadIndicator) {
                this.el.dom.innerHTML = this.indicatorText;
            }
        },


        abort: function () {
            if (this.transaction) {
                Ext.Ajax.abort(this.transaction);
            }
        },


        isUpdating: function () {
            return this.transaction ? Ext.Ajax.isLoading(this.transaction) : false;
        },


        refresh: function (callback) {
            if (this.defaultUrl) {
                this.update(this.defaultUrl, null, callback, true);
            }
        }
    };
} ());


Ext.Updater.defaults = {

    timeout: 30,

    disableCaching: false,

    showLoadIndicator: true,

    indicatorText: '<div class="loading-indicator">Loading...</div>',

    loadScripts: false,

    sslBlankUrl: Ext.SSL_SECURE_URL
};



Ext.Updater.updateElement = function (el, url, params, options) {
    var um = Ext.get(el).getUpdater();
    Ext.apply(um, options);
    um.update(url, params, options ? options.callback : null);
};


Ext.Updater.BasicRenderer = function () { };

Ext.Updater.BasicRenderer.prototype = {

    render: function (el, response, updateManager, callback) {
        el.update(response.responseText, updateManager.loadScripts, callback);
    }
};



(function () {


    Date.useStrict = false;





    function xf(format) {
        var args = Array.prototype.slice.call(arguments, 1);
        return format.replace(/\{(\d+)\}/g, function (m, i) {
            return args[i];
        });
    }



    Date.formatCodeToRegex = function (character, currentGroup) {

        var p = Date.parseCodes[character];

        if (p) {
            p = typeof p == 'function' ? p() : p;
            Date.parseCodes[character] = p;
        }

        return p ? Ext.applyIf({
            c: p.c ? xf(p.c, currentGroup || "{0}") : p.c
        }, p) : {
            g: 0,
            c: null,
            s: Ext.escapeRe(character)
        };
    };


    var $f = Date.formatCodeToRegex;

    Ext.apply(Date, {

        parseFunctions: {
            "M$": function (input, strict) {


                var re = new RegExp('\\/Date\\(([-+])?(\\d+)(?:[+-]\\d{4})?\\)\\/');
                var r = (input || '').match(re);
                return r ? new Date(((r[1] || '') + r[2]) * 1) : null;
            }
        },
        parseRegexes: [],


        formatFunctions: {
            "M$": function () {

                return '\\/Date(' + this.getTime() + ')\\/';
            }
        },

        y2kYear: 50,


        MILLI: "ms",


        SECOND: "s",


        MINUTE: "mi",


        HOUR: "h",


        DAY: "d",


        MONTH: "mo",


        YEAR: "y",


        defaults: {},


        dayNames: [
        "Sunday",
        "Monday",
        "Tuesday",
        "Wednesday",
        "Thursday",
        "Friday",
        "Saturday"
    ],


        monthNames: [
        "January",
        "February",
        "March",
        "April",
        "May",
        "June",
        "July",
        "August",
        "September",
        "October",
        "November",
        "December"
    ],


        monthNumbers: {
            Jan: 0,
            Feb: 1,
            Mar: 2,
            Apr: 3,
            May: 4,
            Jun: 5,
            Jul: 6,
            Aug: 7,
            Sep: 8,
            Oct: 9,
            Nov: 10,
            Dec: 11
        },


        getShortMonthName: function (month) {
            return Date.monthNames[month].substring(0, 3);
        },


        getShortDayName: function (day) {
            return Date.dayNames[day].substring(0, 3);
        },


        getMonthNumber: function (name) {

            return Date.monthNumbers[name.substring(0, 1).toUpperCase() + name.substring(1, 3).toLowerCase()];
        },


        formatCodes: {
            d: "String.leftPad(this.getDate(), 2, '0')",
            D: "Date.getShortDayName(this.getDay())",
            j: "this.getDate()",
            l: "Date.dayNames[this.getDay()]",
            N: "(this.getDay() ? this.getDay() : 7)",
            S: "this.getSuffix()",
            w: "this.getDay()",
            z: "this.getDayOfYear()",
            W: "String.leftPad(this.getWeekOfYear(), 2, '0')",
            F: "Date.monthNames[this.getMonth()]",
            m: "String.leftPad(this.getMonth() + 1, 2, '0')",
            M: "Date.getShortMonthName(this.getMonth())",
            n: "(this.getMonth() + 1)",
            t: "this.getDaysInMonth()",
            L: "(this.isLeapYear() ? 1 : 0)",
            o: "(this.getFullYear() + (this.getWeekOfYear() == 1 && this.getMonth() > 0 ? +1 : (this.getWeekOfYear() >= 52 && this.getMonth() < 11 ? -1 : 0)))",
            Y: "String.leftPad(this.getFullYear(), 4, '0')",
            y: "('' + this.getFullYear()).substring(2, 4)",
            a: "(this.getHours() < 12 ? 'am' : 'pm')",
            A: "(this.getHours() < 12 ? 'AM' : 'PM')",
            g: "((this.getHours() % 12) ? this.getHours() % 12 : 12)",
            G: "this.getHours()",
            h: "String.leftPad((this.getHours() % 12) ? this.getHours() % 12 : 12, 2, '0')",
            H: "String.leftPad(this.getHours(), 2, '0')",
            i: "String.leftPad(this.getMinutes(), 2, '0')",
            s: "String.leftPad(this.getSeconds(), 2, '0')",
            u: "String.leftPad(this.getMilliseconds(), 3, '0')",
            O: "this.getGMTOffset()",
            P: "this.getGMTOffset(true)",
            T: "this.getTimezone()",
            Z: "(this.getTimezoneOffset() * -60)",

            c: function () {
                for (var c = "Y-m-dTH:i:sP", code = [], i = 0, l = c.length; i < l; ++i) {
                    var e = c.charAt(i);
                    code.push(e == "T" ? "'T'" : Date.getFormatCode(e));
                }
                return code.join(" + ");
            },


            U: "Math.round(this.getTime() / 1000)"
        },


        isValid: function (y, m, d, h, i, s, ms) {

            h = h || 0;
            i = i || 0;
            s = s || 0;
            ms = ms || 0;


            var dt = new Date(y < 100 ? 100 : y, m - 1, d, h, i, s, ms).add(Date.YEAR, y < 100 ? y - 100 : 0);

            return y == dt.getFullYear() &&
            m == dt.getMonth() + 1 &&
            d == dt.getDate() &&
            h == dt.getHours() &&
            i == dt.getMinutes() &&
            s == dt.getSeconds() &&
            ms == dt.getMilliseconds();
        },


        parseDate: function (input, format, strict) {
            var p = Date.parseFunctions;
            if (p[format] == null) {
                Date.createParser(format);
            }
            return p[format](input, Ext.isDefined(strict) ? strict : Date.useStrict);
        },


        getFormatCode: function (character) {
            var f = Date.formatCodes[character];

            if (f) {
                f = typeof f == 'function' ? f() : f;
                Date.formatCodes[character] = f;
            }


            return f || ("'" + String.escape(character) + "'");
        },


        createFormat: function (format) {
            var code = [],
            special = false,
            ch = '';

            for (var i = 0; i < format.length; ++i) {
                ch = format.charAt(i);
                if (!special && ch == "\\") {
                    special = true;
                } else if (special) {
                    special = false;
                    code.push("'" + String.escape(ch) + "'");
                } else {
                    code.push(Date.getFormatCode(ch));
                }
            }
            Date.formatFunctions[format] = new Function("return " + code.join('+'));
        },


        createParser: function () {
            var code = [
            "var dt, y, m, d, h, i, s, ms, o, z, zz, u, v,",
                "def = Date.defaults,",
                "results = String(input).match(Date.parseRegexes[{0}]);",

            "if(results){",
                "{1}",

                "if(u != null){",
                    "v = new Date(u * 1000);",
                "}else{",



                    "dt = (new Date()).clearTime();",


                    "y = Ext.num(y, Ext.num(def.y, dt.getFullYear()));",
                    "m = Ext.num(m, Ext.num(def.m - 1, dt.getMonth()));",
                    "d = Ext.num(d, Ext.num(def.d, dt.getDate()));",


                    "h  = Ext.num(h, Ext.num(def.h, dt.getHours()));",
                    "i  = Ext.num(i, Ext.num(def.i, dt.getMinutes()));",
                    "s  = Ext.num(s, Ext.num(def.s, dt.getSeconds()));",
                    "ms = Ext.num(ms, Ext.num(def.ms, dt.getMilliseconds()));",

                    "if(z >= 0 && y >= 0){",





                        "v = new Date(y < 100 ? 100 : y, 0, 1, h, i, s, ms).add(Date.YEAR, y < 100 ? y - 100 : 0);",


                        "v = !strict? v : (strict === true && (z <= 364 || (v.isLeapYear() && z <= 365))? v.add(Date.DAY, z) : null);",
                    "}else if(strict === true && !Date.isValid(y, m + 1, d, h, i, s, ms)){",
                        "v = null;",
                    "}else{",


                        "v = new Date(y < 100 ? 100 : y, m, d, h, i, s, ms).add(Date.YEAR, y < 100 ? y - 100 : 0);",
                    "}",
                "}",
            "}",

            "if(v){",

                "if(zz != null){",

                    "v = v.add(Date.SECOND, -v.getTimezoneOffset() * 60 - zz);",
                "}else if(o){",

                    "v = v.add(Date.MINUTE, -v.getTimezoneOffset() + (sn == '+'? -1 : 1) * (hr * 60 + mn));",
                "}",
            "}",

            "return v;"
        ].join('\n');

            return function (format) {
                var regexNum = Date.parseRegexes.length,
                currentGroup = 1,
                calc = [],
                regex = [],
                special = false,
                ch = "";

                for (var i = 0; i < format.length; ++i) {
                    ch = format.charAt(i);
                    if (!special && ch == "\\") {
                        special = true;
                    } else if (special) {
                        special = false;
                        regex.push(String.escape(ch));
                    } else {
                        var obj = $f(ch, currentGroup);
                        currentGroup += obj.g;
                        regex.push(obj.s);
                        if (obj.g && obj.c) {
                            calc.push(obj.c);
                        }
                    }
                }

                Date.parseRegexes[regexNum] = new RegExp("^" + regex.join('') + "$", 'i');
                Date.parseFunctions[format] = new Function("input", "strict", xf(code, regexNum, calc.join('')));
            };
        } (),


        parseCodes: {

            d: {
                g: 1,
                c: "d = parseInt(results[{0}], 10);\n",
                s: "(\\d{2})"
            },
            j: {
                g: 1,
                c: "d = parseInt(results[{0}], 10);\n",
                s: "(\\d{1,2})"
            },
            D: function () {
                for (var a = [], i = 0; i < 7; a.push(Date.getShortDayName(i)), ++i);
                return {
                    g: 0,
                    c: null,
                    s: "(?:" + a.join("|") + ")"
                };
            },
            l: function () {
                return {
                    g: 0,
                    c: null,
                    s: "(?:" + Date.dayNames.join("|") + ")"
                };
            },
            N: {
                g: 0,
                c: null,
                s: "[1-7]"
            },
            S: {
                g: 0,
                c: null,
                s: "(?:st|nd|rd|th)"
            },
            w: {
                g: 0,
                c: null,
                s: "[0-6]"
            },
            z: {
                g: 1,
                c: "z = parseInt(results[{0}], 10);\n",
                s: "(\\d{1,3})"
            },
            W: {
                g: 0,
                c: null,
                s: "(?:\\d{2})"
            },
            F: function () {
                return {
                    g: 1,
                    c: "m = parseInt(Date.getMonthNumber(results[{0}]), 10);\n",
                    s: "(" + Date.monthNames.join("|") + ")"
                };
            },
            M: function () {
                for (var a = [], i = 0; i < 12; a.push(Date.getShortMonthName(i)), ++i);
                return Ext.applyIf({
                    s: "(" + a.join("|") + ")"
                }, $f("F"));
            },
            m: {
                g: 1,
                c: "m = parseInt(results[{0}], 10) - 1;\n",
                s: "(\\d{2})"
            },
            n: {
                g: 1,
                c: "m = parseInt(results[{0}], 10) - 1;\n",
                s: "(\\d{1,2})"
            },
            t: {
                g: 0,
                c: null,
                s: "(?:\\d{2})"
            },
            L: {
                g: 0,
                c: null,
                s: "(?:1|0)"
            },
            o: function () {
                return $f("Y");
            },
            Y: {
                g: 1,
                c: "y = parseInt(results[{0}], 10);\n",
                s: "(\\d{4})"
            },
            y: {
                g: 1,
                c: "var ty = parseInt(results[{0}], 10);\n"
                + "y = ty > Date.y2kYear ? 1900 + ty : 2000 + ty;\n",
                s: "(\\d{1,2})"
            },

            a: {
                g: 1,
                c: "if (/(am)/i.test(results[{0}])) {\n"
                + "if (!h || h == 12) { h = 0; }\n"
                + "} else { if (!h || h < 12) { h = (h || 0) + 12; }}",
                s: "(am|pm|AM|PM)"
            },
            A: {
                g: 1,
                c: "if (/(am)/i.test(results[{0}])) {\n"
                + "if (!h || h == 12) { h = 0; }\n"
                + "} else { if (!h || h < 12) { h = (h || 0) + 12; }}",
                s: "(AM|PM|am|pm)"
            },
            g: function () {
                return $f("G");
            },
            G: {
                g: 1,
                c: "h = parseInt(results[{0}], 10);\n",
                s: "(\\d{1,2})"
            },
            h: function () {
                return $f("H");
            },
            H: {
                g: 1,
                c: "h = parseInt(results[{0}], 10);\n",
                s: "(\\d{2})"
            },
            i: {
                g: 1,
                c: "i = parseInt(results[{0}], 10);\n",
                s: "(\\d{2})"
            },
            s: {
                g: 1,
                c: "s = parseInt(results[{0}], 10);\n",
                s: "(\\d{2})"
            },
            u: {
                g: 1,
                c: "ms = results[{0}]; ms = parseInt(ms, 10)/Math.pow(10, ms.length - 3);\n",
                s: "(\\d+)"
            },
            O: {
                g: 1,
                c: [
                "o = results[{0}];",
                "var sn = o.substring(0,1),",
                    "hr = o.substring(1,3)*1 + Math.floor(o.substring(3,5) / 60),",
                    "mn = o.substring(3,5) % 60;",
                "o = ((-12 <= (hr*60 + mn)/60) && ((hr*60 + mn)/60 <= 14))? (sn + String.leftPad(hr, 2, '0') + String.leftPad(mn, 2, '0')) : null;\n"
            ].join("\n"),
                s: "([+\-]\\d{4})"
            },
            P: {
                g: 1,
                c: [
                "o = results[{0}];",
                "var sn = o.substring(0,1),",
                    "hr = o.substring(1,3)*1 + Math.floor(o.substring(4,6) / 60),",
                    "mn = o.substring(4,6) % 60;",
                "o = ((-12 <= (hr*60 + mn)/60) && ((hr*60 + mn)/60 <= 14))? (sn + String.leftPad(hr, 2, '0') + String.leftPad(mn, 2, '0')) : null;\n"
            ].join("\n"),
                s: "([+\-]\\d{2}:\\d{2})"
            },
            T: {
                g: 0,
                c: null,
                s: "[A-Z]{1,4}"
            },
            Z: {
                g: 1,
                c: "zz = results[{0}] * 1;\n"
                  + "zz = (-43200 <= zz && zz <= 50400)? zz : null;\n",
                s: "([+\-]?\\d{1,5})"
            },
            c: function () {
                var calc = [],
                arr = [
                    $f("Y", 1),
                    $f("m", 2),
                    $f("d", 3),
                    $f("h", 4),
                    $f("i", 5),
                    $f("s", 6),
                    { c: "ms = results[7] || '0'; ms = parseInt(ms, 10)/Math.pow(10, ms.length - 3);\n" },
                    { c: [
                        "if(results[8]) {",
                            "if(results[8] == 'Z'){",
                                "zz = 0;",
                            "}else if (results[8].indexOf(':') > -1){",
                                $f("P", 8).c,
                            "}else{",
                                $f("O", 8).c,
                            "}",
                        "}"
                    ].join('\n')
                    }
                ];

                for (var i = 0, l = arr.length; i < l; ++i) {
                    calc.push(arr[i].c);
                }

                return {
                    g: 1,
                    c: calc.join(""),
                    s: [
                    arr[0].s,
                    "(?:", "-", arr[1].s,
                        "(?:", "-", arr[2].s,
                            "(?:",
                                "(?:T| )?",
                                arr[3].s, ":", arr[4].s,
                                "(?::", arr[5].s, ")?",
                                "(?:(?:\\.|,)(\\d+))?",
                                "(Z|(?:[-+]\\d{2}(?::)?\\d{2}))?",
                            ")?",
                        ")?",
                    ")?"
                ].join("")
                };
            },
            U: {
                g: 1,
                c: "u = parseInt(results[{0}], 10);\n",
                s: "(-?\\d+)"
            }
        }
    });

} ());

Ext.apply(Date.prototype, {

    dateFormat: function (format) {
        if (Date.formatFunctions[format] == null) {
            Date.createFormat(format);
        }
        return Date.formatFunctions[format].call(this);
    },


    getTimezone: function () {












        return this.toString().replace(/^.* (?:\((.*)\)|([A-Z]{1,4})(?:[\-+][0-9]{4})?(?: -?\d+)?)$/, "$1$2").replace(/[^A-Z]/g, "");
    },


    getGMTOffset: function (colon) {
        return (this.getTimezoneOffset() > 0 ? "-" : "+")
            + String.leftPad(Math.floor(Math.abs(this.getTimezoneOffset()) / 60), 2, "0")
            + (colon ? ":" : "")
            + String.leftPad(Math.abs(this.getTimezoneOffset() % 60), 2, "0");
    },


    getDayOfYear: function () {
        var num = 0,
            d = this.clone(),
            m = this.getMonth(),
            i;

        for (i = 0, d.setDate(1), d.setMonth(0); i < m; d.setMonth(++i)) {
            num += d.getDaysInMonth();
        }
        return num + this.getDate() - 1;
    },


    getWeekOfYear: function () {

        var ms1d = 864e5,
            ms7d = 7 * ms1d;

        return function () {
            var DC3 = Date.UTC(this.getFullYear(), this.getMonth(), this.getDate() + 3) / ms1d,
                AWN = Math.floor(DC3 / 7),
                Wyr = new Date(AWN * ms7d).getUTCFullYear();

            return AWN - Math.floor(Date.UTC(Wyr, 0, 7) / ms7d) + 1;
        };
    } (),


    isLeapYear: function () {
        var year = this.getFullYear();
        return !!((year & 3) == 0 && (year % 100 || (year % 400 == 0 && year)));
    },


    getFirstDayOfMonth: function () {
        var day = (this.getDay() - (this.getDate() - 1)) % 7;
        return (day < 0) ? (day + 7) : day;
    },


    getLastDayOfMonth: function () {
        return this.getLastDateOfMonth().getDay();
    },



    getFirstDateOfMonth: function () {
        return new Date(this.getFullYear(), this.getMonth(), 1);
    },


    getLastDateOfMonth: function () {
        return new Date(this.getFullYear(), this.getMonth(), this.getDaysInMonth());
    },


    getDaysInMonth: function () {
        var daysInMonth = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];

        return function () {
            var m = this.getMonth();

            return m == 1 && this.isLeapYear() ? 29 : daysInMonth[m];
        };
    } (),


    getSuffix: function () {
        switch (this.getDate()) {
            case 1:
            case 21:
            case 31:
                return "st";
            case 2:
            case 22:
                return "nd";
            case 3:
            case 23:
                return "rd";
            default:
                return "th";
        }
    },


    clone: function () {
        return new Date(this.getTime());
    },


    isDST: function () {


        return new Date(this.getFullYear(), 0, 1).getTimezoneOffset() != this.getTimezoneOffset();
    },


    clearTime: function (clone) {
        if (clone) {
            return this.clone().clearTime();
        }


        var d = this.getDate();


        this.setHours(0);
        this.setMinutes(0);
        this.setSeconds(0);
        this.setMilliseconds(0);

        if (this.getDate() != d) {




            for (var hr = 1, c = this.add(Date.HOUR, hr); c.getDate() != d; hr++, c = this.add(Date.HOUR, hr));

            this.setDate(d);
            this.setHours(c.getHours());
        }

        return this;
    },


    add: function (interval, value) {
        var d = this.clone();
        if (!interval || value === 0) return d;

        switch (interval.toLowerCase()) {
            case Date.MILLI:
                d.setMilliseconds(this.getMilliseconds() + value);
                break;
            case Date.SECOND:
                d.setSeconds(this.getSeconds() + value);
                break;
            case Date.MINUTE:
                d.setMinutes(this.getMinutes() + value);
                break;
            case Date.HOUR:
                d.setHours(this.getHours() + value);
                break;
            case Date.DAY:
                d.setDate(this.getDate() + value);
                break;
            case Date.MONTH:
                var day = this.getDate();
                if (day > 28) {
                    day = Math.min(day, this.getFirstDateOfMonth().add('mo', value).getLastDateOfMonth().getDate());
                }
                d.setDate(day);
                d.setMonth(this.getMonth() + value);
                break;
            case Date.YEAR:
                d.setFullYear(this.getFullYear() + value);
                break;
        }
        return d;
    },


    between: function (start, end) {
        var t = this.getTime();
        return start.getTime() <= t && t <= end.getTime();
    }
});



Date.prototype.format = Date.prototype.dateFormat;



if (Ext.isSafari && (navigator.userAgent.match(/WebKit\/(\d+)/)[1] || NaN) < 420) {
    Ext.apply(Date.prototype, {
        _xMonth: Date.prototype.setMonth,
        _xDate: Date.prototype.setDate,



        setMonth: function (num) {
            if (num <= -1) {
                var n = Math.ceil(-num),
                    back_year = Math.ceil(n / 12),
                    month = (n % 12) ? 12 - n % 12 : 0;

                this.setFullYear(this.getFullYear() - back_year);

                return this._xMonth(month);
            } else {
                return this._xMonth(num);
            }
        },




        setDate: function (d) {


            return this.setTime(this.getTime() - (this.getDate() - d) * 864e5);
        }
    });
}





Ext.util.MixedCollection = function (allowFunctions, keyFn) {
    this.items = [];
    this.map = {};
    this.keys = [];
    this.length = 0;
    this.addEvents(

        'clear',

        'add',

        'replace',

        'remove',
        'sort'
    );
    this.allowFunctions = allowFunctions === true;
    if (keyFn) {
        this.getKey = keyFn;
    }
    Ext.util.MixedCollection.superclass.constructor.call(this);
};

Ext.extend(Ext.util.MixedCollection, Ext.util.Observable, {


    allowFunctions: false,


    add: function (key, o) {
        if (arguments.length == 1) {
            o = arguments[0];
            key = this.getKey(o);
        }
        if (typeof key != 'undefined' && key !== null) {
            var old = this.map[key];
            if (typeof old != 'undefined') {
                return this.replace(key, o);
            }
            this.map[key] = o;
        }
        this.length++;
        this.items.push(o);
        this.keys.push(key);
        this.fireEvent('add', this.length - 1, o, key);
        return o;
    },


    getKey: function (o) {
        return o.id;
    },


    replace: function (key, o) {
        if (arguments.length == 1) {
            o = arguments[0];
            key = this.getKey(o);
        }
        var old = this.map[key];
        if (typeof key == 'undefined' || key === null || typeof old == 'undefined') {
            return this.add(key, o);
        }
        var index = this.indexOfKey(key);
        this.items[index] = o;
        this.map[key] = o;
        this.fireEvent('replace', key, old, o);
        return o;
    },


    addAll: function (objs) {
        if (arguments.length > 1 || Ext.isArray(objs)) {
            var args = arguments.length > 1 ? arguments : objs;
            for (var i = 0, len = args.length; i < len; i++) {
                this.add(args[i]);
            }
        } else {
            for (var key in objs) {
                if (this.allowFunctions || typeof objs[key] != 'function') {
                    this.add(key, objs[key]);
                }
            }
        }
    },


    each: function (fn, scope) {
        var items = [].concat(this.items);
        for (var i = 0, len = items.length; i < len; i++) {
            if (fn.call(scope || items[i], items[i], i, len) === false) {
                break;
            }
        }
    },


    eachKey: function (fn, scope) {
        for (var i = 0, len = this.keys.length; i < len; i++) {
            fn.call(scope || window, this.keys[i], this.items[i], i, len);
        }
    },


    find: function (fn, scope) {
        for (var i = 0, len = this.items.length; i < len; i++) {
            if (fn.call(scope || window, this.items[i], this.keys[i])) {
                return this.items[i];
            }
        }
        return null;
    },


    insert: function (index, key, o) {
        if (arguments.length == 2) {
            o = arguments[1];
            key = this.getKey(o);
        }
        if (this.containsKey(key)) {
            this.suspendEvents();
            this.removeKey(key);
            this.resumeEvents();
        }
        if (index >= this.length) {
            return this.add(key, o);
        }
        this.length++;
        this.items.splice(index, 0, o);
        if (typeof key != 'undefined' && key !== null) {
            this.map[key] = o;
        }
        this.keys.splice(index, 0, key);
        this.fireEvent('add', index, o, key);
        return o;
    },


    remove: function (o) {
        return this.removeAt(this.indexOf(o));
    },


    removeAt: function (index) {
        if (index < this.length && index >= 0) {
            this.length--;
            var o = this.items[index];
            this.items.splice(index, 1);
            var key = this.keys[index];
            if (typeof key != 'undefined') {
                delete this.map[key];
            }
            this.keys.splice(index, 1);
            this.fireEvent('remove', o, key);
            return o;
        }
        return false;
    },


    removeKey: function (key) {
        return this.removeAt(this.indexOfKey(key));
    },


    getCount: function () {
        return this.length;
    },


    indexOf: function (o) {
        return this.items.indexOf(o);
    },


    indexOfKey: function (key) {
        return this.keys.indexOf(key);
    },


    item: function (key) {
        var mk = this.map[key],
            item = mk !== undefined ? mk : (typeof key == 'number') ? this.items[key] : undefined;
        return typeof item != 'function' || this.allowFunctions ? item : null;
    },


    itemAt: function (index) {
        return this.items[index];
    },


    key: function (key) {
        return this.map[key];
    },


    contains: function (o) {
        return this.indexOf(o) != -1;
    },


    containsKey: function (key) {
        return typeof this.map[key] != 'undefined';
    },


    clear: function () {
        this.length = 0;
        this.items = [];
        this.keys = [];
        this.map = {};
        this.fireEvent('clear');
    },


    first: function () {
        return this.items[0];
    },


    last: function () {
        return this.items[this.length - 1];
    },


    _sort: function (property, dir, fn) {
        var i, len,
            dsc = String(dir).toUpperCase() == 'DESC' ? -1 : 1,


            c = [],
            keys = this.keys,
            items = this.items;


        fn = fn || function (a, b) {
            return a - b;
        };


        for (i = 0, len = items.length; i < len; i++) {
            c[c.length] = {
                key: keys[i],
                value: items[i],
                index: i
            };
        }


        c.sort(function (a, b) {
            var v = fn(a[property], b[property]) * dsc;
            if (v === 0) {
                v = (a.index < b.index ? -1 : 1);
            }
            return v;
        });


        for (i = 0, len = c.length; i < len; i++) {
            items[i] = c[i].value;
            keys[i] = c[i].key;
        }

        this.fireEvent('sort', this);
    },


    sort: function (dir, fn) {
        this._sort('value', dir, fn);
    },


    reorder: function (mapping) {
        this.suspendEvents();

        var items = this.items,
            index = 0,
            length = items.length,
            order = [],
            remaining = [],
            oldIndex;


        for (oldIndex in mapping) {
            order[mapping[oldIndex]] = items[oldIndex];
        }

        for (index = 0; index < length; index++) {
            if (mapping[index] == undefined) {
                remaining.push(items[index]);
            }
        }

        for (index = 0; index < length; index++) {
            if (order[index] == undefined) {
                order[index] = remaining.shift();
            }
        }

        this.clear();
        this.addAll(order);

        this.resumeEvents();
        this.fireEvent('sort', this);
    },


    keySort: function (dir, fn) {
        this._sort('key', dir, fn || function (a, b) {
            var v1 = String(a).toUpperCase(), v2 = String(b).toUpperCase();
            return v1 > v2 ? 1 : (v1 < v2 ? -1 : 0);
        });
    },


    getRange: function (start, end) {
        var items = this.items;
        if (items.length < 1) {
            return [];
        }
        start = start || 0;
        end = Math.min(typeof end == 'undefined' ? this.length - 1 : end, this.length - 1);
        var i, r = [];
        if (start <= end) {
            for (i = start; i <= end; i++) {
                r[r.length] = items[i];
            }
        } else {
            for (i = start; i >= end; i--) {
                r[r.length] = items[i];
            }
        }
        return r;
    },


    filter: function (property, value, anyMatch, caseSensitive) {
        if (Ext.isEmpty(value, false)) {
            return this.clone();
        }
        value = this.createValueMatcher(value, anyMatch, caseSensitive);
        return this.filterBy(function (o) {
            return o && value.test(o[property]);
        });
    },


    filterBy: function (fn, scope) {
        var r = new Ext.util.MixedCollection();
        r.getKey = this.getKey;
        var k = this.keys, it = this.items;
        for (var i = 0, len = it.length; i < len; i++) {
            if (fn.call(scope || this, it[i], k[i])) {
                r.add(k[i], it[i]);
            }
        }
        return r;
    },


    findIndex: function (property, value, start, anyMatch, caseSensitive) {
        if (Ext.isEmpty(value, false)) {
            return -1;
        }
        value = this.createValueMatcher(value, anyMatch, caseSensitive);
        return this.findIndexBy(function (o) {
            return o && value.test(o[property]);
        }, null, start);
    },


    findIndexBy: function (fn, scope, start) {
        var k = this.keys, it = this.items;
        for (var i = (start || 0), len = it.length; i < len; i++) {
            if (fn.call(scope || this, it[i], k[i])) {
                return i;
            }
        }
        return -1;
    },


    createValueMatcher: function (value, anyMatch, caseSensitive, exactMatch) {
        if (!value.exec) {
            var er = Ext.escapeRe;
            value = String(value);

            if (anyMatch === true) {
                value = er(value);
            } else {
                value = '^' + er(value);
                if (exactMatch === true) {
                    value += '$';
                }
            }
            value = new RegExp(value, caseSensitive ? '' : 'i');
        }
        return value;
    },


    clone: function () {
        var r = new Ext.util.MixedCollection();
        var k = this.keys, it = this.items;
        for (var i = 0, len = it.length; i < len; i++) {
            r.add(k[i], it[i]);
        }
        r.getKey = this.getKey;
        return r;
    }
});

Ext.util.MixedCollection.prototype.get = Ext.util.MixedCollection.prototype.item;

Ext.AbstractManager = Ext.extend(Object, {
    typeName: 'type',

    constructor: function (config) {
        Ext.apply(this, config || {});


        this.all = new Ext.util.MixedCollection();

        this.types = {};
    },


    get: function (id) {
        return this.all.get(id);
    },


    register: function (item) {
        this.all.add(item);
    },


    unregister: function (item) {
        this.all.remove(item);
    },


    registerType: function (type, cls) {
        this.types[type] = cls;
        cls[this.typeName] = type;
    },


    isRegistered: function (type) {
        return this.types[type] !== undefined;
    },


    create: function (config, defaultType) {
        var type = config[this.typeName] || config.type || defaultType,
            Constructor = this.types[type];

        if (Constructor == undefined) {
            throw new Error(String.format("The '{0}' type has not been registered with this manager", type));
        }

        return new Constructor(config);
    },


    onAvailable: function (id, fn, scope) {
        var all = this.all;

        all.on("add", function (index, o) {
            if (o.id == id) {
                fn.call(scope || o, o);
                all.un("add", fn, scope);
            }
        });
    }
});
Ext.util.Format = function () {
    var trimRe = /^\s+|\s+$/g,
        stripTagsRE = /<\/?[^>]+>/gi,
        stripScriptsRe = /(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)/ig,
        nl2brRe = /\r?\n/g;

    return {

        ellipsis: function (value, len, word) {
            if (value && value.length > len) {
                if (word) {
                    var vs = value.substr(0, len - 2),
                        index = Math.max(vs.lastIndexOf(' '), vs.lastIndexOf('.'), vs.lastIndexOf('!'), vs.lastIndexOf('?'));
                    if (index == -1 || index < (len - 15)) {
                        return value.substr(0, len - 3) + "...";
                    } else {
                        return vs.substr(0, index) + "...";
                    }
                } else {
                    return value.substr(0, len - 3) + "...";
                }
            }
            return value;
        },


        undef: function (value) {
            return value !== undefined ? value : "";
        },


        defaultValue: function (value, defaultValue) {
            return value !== undefined && value !== '' ? value : defaultValue;
        },


        htmlEncode: function (value) {
            return !value ? value : String(value).replace(/&/g, "&amp;").replace(/>/g, "&gt;").replace(/</g, "&lt;").replace(/"/g, "&quot;");
        },


        htmlDecode: function (value) {
            return !value ? value : String(value).replace(/&gt;/g, ">").replace(/&lt;/g, "<").replace(/&quot;/g, '"').replace(/&amp;/g, "&");
        },


        trim: function (value) {
            return String(value).replace(trimRe, "");
        },


        substr: function (value, start, length) {
            return String(value).substr(start, length);
        },


        lowercase: function (value) {
            return String(value).toLowerCase();
        },


        uppercase: function (value) {
            return String(value).toUpperCase();
        },


        capitalize: function (value) {
            return !value ? value : value.charAt(0).toUpperCase() + value.substr(1).toLowerCase();
        },


        call: function (value, fn) {
            if (arguments.length > 2) {
                var args = Array.prototype.slice.call(arguments, 2);
                args.unshift(value);
                return eval(fn).apply(window, args);
            } else {
                return eval(fn).call(window, value);
            }
        },


        usMoney: function (v) {
            v = (Math.round((v - 0) * 100)) / 100;
            v = (v == Math.floor(v)) ? v + ".00" : ((v * 10 == Math.floor(v * 10)) ? v + "0" : v);
            v = String(v);
            var ps = v.split('.'),
                whole = ps[0],
                sub = ps[1] ? '.' + ps[1] : '.00',
                r = /(\d+)(\d{3})/;
            while (r.test(whole)) {
                whole = whole.replace(r, '$1' + ',' + '$2');
            }
            v = whole + sub;
            if (v.charAt(0) == '-') {
                return '-$' + v.substr(1);
            }
            return "$" + v;
        },


        date: function (v, format) {
            if (!v) {
                return "";
            }
            if (!Ext.isDate(v)) {
                v = new Date(Date.parse(v));
            }
            return v.dateFormat(format || "m/d/Y");
        },


        dateRenderer: function (format) {
            return function (v) {
                return Ext.util.Format.date(v, format);
            };
        },


        stripTags: function (v) {
            return !v ? v : String(v).replace(stripTagsRE, "");
        },


        stripScripts: function (v) {
            return !v ? v : String(v).replace(stripScriptsRe, "");
        },


        fileSize: function (size) {
            if (size < 1024) {
                return size + " bytes";
            } else if (size < 1048576) {
                return (Math.round(((size * 10) / 1024)) / 10) + " KB";
            } else {
                return (Math.round(((size * 10) / 1048576)) / 10) + " MB";
            }
        },


        math: function () {
            var fns = {};

            return function (v, a) {
                if (!fns[a]) {
                    fns[a] = new Function('v', 'return v ' + a + ';');
                }
                return fns[a](v);
            };
        } (),


        round: function (value, precision) {
            var result = Number(value);
            if (typeof precision == 'number') {
                precision = Math.pow(10, precision);
                result = Math.round(value * precision) / precision;
            }
            return result;
        },


        number: function (v, format) {
            if (!format) {
                return v;
            }
            v = Ext.num(v, NaN);
            if (isNaN(v)) {
                return '';
            }
            var comma = ',',
                dec = '.',
                i18n = false,
                neg = v < 0;

            v = Math.abs(v);
            if (format.substr(format.length - 2) == '/i') {
                format = format.substr(0, format.length - 2);
                i18n = true;
                comma = '.';
                dec = ',';
            }

            var hasComma = format.indexOf(comma) != -1,
                psplit = (i18n ? format.replace(/[^\d\,]/g, '') : format.replace(/[^\d\.]/g, '')).split(dec);

            if (1 < psplit.length) {
                v = v.toFixed(psplit[1].length);
            } else if (2 < psplit.length) {
                throw ('NumberFormatException: invalid format, formats should have no more than 1 period: ' + format);
            } else {
                v = v.toFixed(0);
            }

            var fnum = v.toString();

            psplit = fnum.split('.');

            if (hasComma) {
                var cnum = psplit[0],
                    parr = [],
                    j = cnum.length,
                    m = Math.floor(j / 3),
                    n = cnum.length % 3 || 3,
                    i;

                for (i = 0; i < j; i += n) {
                    if (i != 0) {
                        n = 3;
                    }

                    parr[parr.length] = cnum.substr(i, n);
                    m -= 1;
                }
                fnum = parr.join(comma);
                if (psplit[1]) {
                    fnum += dec + psplit[1];
                }
            } else {
                if (psplit[1]) {
                    fnum = psplit[0] + dec + psplit[1];
                }
            }

            return (neg ? '-' : '') + format.replace(/[\d,?\.?]+/, fnum);
        },


        numberRenderer: function (format) {
            return function (v) {
                return Ext.util.Format.number(v, format);
            };
        },


        plural: function (v, s, p) {
            return v + ' ' + (v == 1 ? s : (p ? p : s + 's'));
        },


        nl2br: function (v) {
            return Ext.isEmpty(v) ? '' : v.replace(nl2brRe, '<br/>');
        }
    };
} ();

Ext.XTemplate = function () {
    Ext.XTemplate.superclass.constructor.apply(this, arguments);

    var me = this,
        s = me.html,
        re = /<tpl\b[^>]*>((?:(?=([^<]+))\2|<(?!tpl\b[^>]*>))*?)<\/tpl>/,
        nameRe = /^<tpl\b[^>]*?for="(.*?)"/,
        ifRe = /^<tpl\b[^>]*?if="(.*?)"/,
        execRe = /^<tpl\b[^>]*?exec="(.*?)"/,
        m,
        id = 0,
        tpls = [],
        VALUES = 'values',
        PARENT = 'parent',
        XINDEX = 'xindex',
        XCOUNT = 'xcount',
        RETURN = 'return ',
        WITHVALUES = 'with(values){ ';

    s = ['<tpl>', s, '</tpl>'].join('');

    while ((m = s.match(re))) {
        var m2 = m[0].match(nameRe),
            m3 = m[0].match(ifRe),
            m4 = m[0].match(execRe),
            exp = null,
            fn = null,
            exec = null,
            name = m2 && m2[1] ? m2[1] : '';

        if (m3) {
            exp = m3 && m3[1] ? m3[1] : null;
            if (exp) {
                fn = new Function(VALUES, PARENT, XINDEX, XCOUNT, WITHVALUES + RETURN + (Ext.util.Format.htmlDecode(exp)) + '; }');
            }
        }
        if (m4) {
            exp = m4 && m4[1] ? m4[1] : null;
            if (exp) {
                exec = new Function(VALUES, PARENT, XINDEX, XCOUNT, WITHVALUES + (Ext.util.Format.htmlDecode(exp)) + '; }');
            }
        }
        if (name) {
            switch (name) {
                case '.': name = new Function(VALUES, PARENT, WITHVALUES + RETURN + VALUES + '; }'); break;
                case '..': name = new Function(VALUES, PARENT, WITHVALUES + RETURN + PARENT + '; }'); break;
                default: name = new Function(VALUES, PARENT, WITHVALUES + RETURN + name + '; }');
            }
        }
        tpls.push({
            id: id,
            target: name,
            exec: exec,
            test: fn,
            body: m[1] || ''
        });
        s = s.replace(m[0], '{xtpl' + id + '}');
        ++id;
    }
    for (var i = tpls.length - 1; i >= 0; --i) {
        me.compileTpl(tpls[i]);
    }
    me.master = tpls[tpls.length - 1];
    me.tpls = tpls;
};
Ext.extend(Ext.XTemplate, Ext.Template, {

    re: /\{([\w-\.\#]+)(?:\:([\w\.]*)(?:\((.*?)?\))?)?(\s?[\+\-\*\\]\s?[\d\.\+\-\*\\\(\)]+)?\}/g,

    codeRe: /\{\[((?:\\\]|.|\n)*?)\]\}/g,


    applySubTemplate: function (id, values, parent, xindex, xcount) {
        var me = this,
            len,
            t = me.tpls[id],
            vs,
            buf = [];
        if ((t.test && !t.test.call(me, values, parent, xindex, xcount)) ||
            (t.exec && t.exec.call(me, values, parent, xindex, xcount))) {
            return '';
        }
        vs = t.target ? t.target.call(me, values, parent) : values;
        len = vs.length;
        parent = t.target ? values : parent;
        if (t.target && Ext.isArray(vs)) {
            for (var i = 0, len = vs.length; i < len; i++) {
                buf[buf.length] = t.compiled.call(me, vs[i], parent, i + 1, len);
            }
            return buf.join('');
        }
        return t.compiled.call(me, vs, parent, xindex, xcount);
    },


    compileTpl: function (tpl) {
        var fm = Ext.util.Format,
            useF = this.disableFormats !== true,
            sep = Ext.isGecko ? "+" : ",",
            body;

        function fn(m, name, format, args, math) {
            if (name.substr(0, 4) == 'xtpl') {
                return "'" + sep + 'this.applySubTemplate(' + name.substr(4) + ', values, parent, xindex, xcount)' + sep + "'";
            }
            var v;
            if (name === '.') {
                v = 'values';
            } else if (name === '#') {
                v = 'xindex';
            } else if (name.indexOf('.') != -1) {
                v = name;
            } else {
                v = "values['" + name + "']";
            }
            if (math) {
                v = '(' + v + math + ')';
            }
            if (format && useF) {
                args = args ? ',' + args : "";
                if (format.substr(0, 5) != "this.") {
                    format = "fm." + format + '(';
                } else {
                    format = 'this.call("' + format.substr(5) + '", ';
                    args = ", values";
                }
            } else {
                args = ''; format = "(" + v + " === undefined ? '' : ";
            }
            return "'" + sep + format + v + args + ")" + sep + "'";
        }

        function codeFn(m, code) {

            return "'" + sep + '(' + code.replace(/\\'/g, "'") + ')' + sep + "'";
        }


        if (Ext.isGecko) {
            body = "tpl.compiled = function(values, parent, xindex, xcount){ return '" +
                   tpl.body.replace(/(\r\n|\n)/g, '\\n').replace(/'/g, "\\'").replace(this.re, fn).replace(this.codeRe, codeFn) +
                    "';};";
        } else {
            body = ["tpl.compiled = function(values, parent, xindex, xcount){ return ['"];
            body.push(tpl.body.replace(/(\r\n|\n)/g, '\\n').replace(/'/g, "\\'").replace(this.re, fn).replace(this.codeRe, codeFn));
            body.push("'].join('');};");
            body = body.join('');
        }
        eval(body);
        return this;
    },


    applyTemplate: function (values) {
        return this.master.compiled.call(this, values, {}, 1, 1);
    },


    compile: function () { return this; }





});

Ext.XTemplate.prototype.apply = Ext.XTemplate.prototype.applyTemplate;


Ext.XTemplate.from = function (el) {
    el = Ext.getDom(el);
    return new Ext.XTemplate(el.value || el.innerHTML);
};

Ext.util.CSS = function () {
    var rules = null;
    var doc = document;

    var camelRe = /(-[a-z])/gi;
    var camelFn = function (m, a) { return a.charAt(1).toUpperCase(); };

    return {

        createStyleSheet: function (cssText, id) {
            var ss;
            var head = doc.getElementsByTagName("head")[0];
            var rules = doc.createElement("style");
            rules.setAttribute("type", "text/css");
            if (id) {
                rules.setAttribute("id", id);
            }
            if (Ext.isIE) {
                head.appendChild(rules);
                ss = rules.styleSheet;
                ss.cssText = cssText;
            } else {
                try {
                    rules.appendChild(doc.createTextNode(cssText));
                } catch (e) {
                    rules.cssText = cssText;
                }
                head.appendChild(rules);
                ss = rules.styleSheet ? rules.styleSheet : (rules.sheet || doc.styleSheets[doc.styleSheets.length - 1]);
            }
            this.cacheStyleSheet(ss);
            return ss;
        },


        removeStyleSheet: function (id) {
            var existing = doc.getElementById(id);
            if (existing) {
                existing.parentNode.removeChild(existing);
            }
        },


        swapStyleSheet: function (id, url) {
            this.removeStyleSheet(id);
            var ss = doc.createElement("link");
            ss.setAttribute("rel", "stylesheet");
            ss.setAttribute("type", "text/css");
            ss.setAttribute("id", id);
            ss.setAttribute("href", url);
            doc.getElementsByTagName("head")[0].appendChild(ss);
        },


        refreshCache: function () {
            return this.getRules(true);
        },


        cacheStyleSheet: function (ss) {
            if (!rules) {
                rules = {};
            }
            try {
                var ssRules = ss.cssRules || ss.rules;
                for (var j = ssRules.length - 1; j >= 0; --j) {
                    rules[ssRules[j].selectorText.toLowerCase()] = ssRules[j];
                }
            } catch (e) { }
        },


        getRules: function (refreshCache) {
            if (rules === null || refreshCache) {
                rules = {};
                var ds = doc.styleSheets;
                for (var i = 0, len = ds.length; i < len; i++) {
                    try {
                        this.cacheStyleSheet(ds[i]);
                    } catch (e) { }
                }
            }
            return rules;
        },


        getRule: function (selector, refreshCache) {
            var rs = this.getRules(refreshCache);
            if (!Ext.isArray(selector)) {
                return rs[selector.toLowerCase()];
            }
            for (var i = 0; i < selector.length; i++) {
                if (rs[selector[i]]) {
                    return rs[selector[i].toLowerCase()];
                }
            }
            return null;
        },



        updateRule: function (selector, property, value) {
            if (!Ext.isArray(selector)) {
                var rule = this.getRule(selector);
                if (rule) {
                    rule.style[property.replace(camelRe, camelFn)] = value;
                    return true;
                }
            } else {
                for (var i = 0; i < selector.length; i++) {
                    if (this.updateRule(selector[i], property, value)) {
                        return true;
                    }
                }
            }
            return false;
        }
    };
} ();
Ext.util.ClickRepeater = Ext.extend(Ext.util.Observable, {

    constructor: function (el, config) {
        this.el = Ext.get(el);
        this.el.unselectable();

        Ext.apply(this, config);

        this.addEvents(

        "mousedown",

        "click",

        "mouseup"
        );

        if (!this.disabled) {
            this.disabled = true;
            this.enable();
        }


        if (this.handler) {
            this.on("click", this.handler, this.scope || this);
        }

        Ext.util.ClickRepeater.superclass.constructor.call(this);
    },

    interval: 20,
    delay: 250,
    preventDefault: true,
    stopDefault: false,
    timer: 0,


    enable: function () {
        if (this.disabled) {
            this.el.on('mousedown', this.handleMouseDown, this);
            if (Ext.isIE) {
                this.el.on('dblclick', this.handleDblClick, this);
            }
            if (this.preventDefault || this.stopDefault) {
                this.el.on('click', this.eventOptions, this);
            }
        }
        this.disabled = false;
    },


    disable: function (force) {
        if (force || !this.disabled) {
            clearTimeout(this.timer);
            if (this.pressClass) {
                this.el.removeClass(this.pressClass);
            }
            Ext.getDoc().un('mouseup', this.handleMouseUp, this);
            this.el.removeAllListeners();
        }
        this.disabled = true;
    },


    setDisabled: function (disabled) {
        this[disabled ? 'disable' : 'enable']();
    },

    eventOptions: function (e) {
        if (this.preventDefault) {
            e.preventDefault();
        }
        if (this.stopDefault) {
            e.stopEvent();
        }
    },


    destroy: function () {
        this.disable(true);
        Ext.destroy(this.el);
        this.purgeListeners();
    },

    handleDblClick: function (e) {
        clearTimeout(this.timer);
        this.el.blur();

        this.fireEvent("mousedown", this, e);
        this.fireEvent("click", this, e);
    },


    handleMouseDown: function (e) {
        clearTimeout(this.timer);
        this.el.blur();
        if (this.pressClass) {
            this.el.addClass(this.pressClass);
        }
        this.mousedownTime = new Date();

        Ext.getDoc().on("mouseup", this.handleMouseUp, this);
        this.el.on("mouseout", this.handleMouseOut, this);

        this.fireEvent("mousedown", this, e);
        this.fireEvent("click", this, e);


        if (this.accelerate) {
            this.delay = 400;
        }
        this.timer = this.click.defer(this.delay || this.interval, this, [e]);
    },


    click: function (e) {
        this.fireEvent("click", this, e);
        this.timer = this.click.defer(this.accelerate ?
            this.easeOutExpo(this.mousedownTime.getElapsed(),
                400,
                -390,
                12000) :
            this.interval, this, [e]);
    },

    easeOutExpo: function (t, b, c, d) {
        return (t == d) ? b + c : c * (-Math.pow(2, -10 * t / d) + 1) + b;
    },


    handleMouseOut: function () {
        clearTimeout(this.timer);
        if (this.pressClass) {
            this.el.removeClass(this.pressClass);
        }
        this.el.on("mouseover", this.handleMouseReturn, this);
    },


    handleMouseReturn: function () {
        this.el.un("mouseover", this.handleMouseReturn, this);
        if (this.pressClass) {
            this.el.addClass(this.pressClass);
        }
        this.click();
    },


    handleMouseUp: function (e) {
        clearTimeout(this.timer);
        this.el.un("mouseover", this.handleMouseReturn, this);
        this.el.un("mouseout", this.handleMouseOut, this);
        Ext.getDoc().un("mouseup", this.handleMouseUp, this);
        this.el.removeClass(this.pressClass);
        this.fireEvent("mouseup", this, e);
    }
});
Ext.KeyNav = function (el, config) {
    this.el = Ext.get(el);
    Ext.apply(this, config);
    if (!this.disabled) {
        this.disabled = true;
        this.enable();
    }
};

Ext.KeyNav.prototype = {

    disabled: false,

    defaultEventAction: "stopEvent",

    forceKeyDown: false,


    relay: function (e) {
        var k = e.getKey(),
            h = this.keyToHandler[k];
        if (h && this[h]) {
            if (this.doRelay(e, this[h], h) !== true) {
                e[this.defaultEventAction]();
            }
        }
    },


    doRelay: function (e, h, hname) {
        return h.call(this.scope || this, e, hname);
    },


    enter: false,
    left: false,
    right: false,
    up: false,
    down: false,
    tab: false,
    esc: false,
    pageUp: false,
    pageDown: false,
    del: false,
    home: false,
    end: false,


    keyToHandler: {
        37: "left",
        39: "right",
        38: "up",
        40: "down",
        33: "pageUp",
        34: "pageDown",
        46: "del",
        36: "home",
        35: "end",
        13: "enter",
        27: "esc",
        9: "tab"
    },

    stopKeyUp: function (e) {
        var k = e.getKey();

        if (k >= 37 && k <= 40) {


            e.stopEvent();
        }
    },


    destroy: function () {
        this.disable();
    },


    enable: function () {
        if (this.disabled) {
            if (Ext.isSafari2) {

                this.el.on('keyup', this.stopKeyUp, this);
            }

            this.el.on(this.isKeydown() ? 'keydown' : 'keypress', this.relay, this);
            this.disabled = false;
        }
    },


    disable: function () {
        if (!this.disabled) {
            if (Ext.isSafari2) {

                this.el.un('keyup', this.stopKeyUp, this);
            }

            this.el.un(this.isKeydown() ? 'keydown' : 'keypress', this.relay, this);
            this.disabled = true;
        }
    },


    setDisabled: function (disabled) {
        this[disabled ? "disable" : "enable"]();
    },


    isKeydown: function () {
        return this.forceKeyDown || Ext.EventManager.useKeydown;
    }
};

Ext.KeyMap = function (el, config, eventName) {
    this.el = Ext.get(el);
    this.eventName = eventName || "keydown";
    this.bindings = [];
    if (config) {
        this.addBinding(config);
    }
    this.enable();
};

Ext.KeyMap.prototype = {

    stopEvent: false,


    addBinding: function (config) {
        if (Ext.isArray(config)) {
            Ext.each(config, function (c) {
                this.addBinding(c);
            }, this);
            return;
        }
        var keyCode = config.key,
            fn = config.fn || config.handler,
            scope = config.scope;

        if (config.stopEvent) {
            this.stopEvent = config.stopEvent;
        }

        if (typeof keyCode == "string") {
            var ks = [];
            var keyString = keyCode.toUpperCase();
            for (var j = 0, len = keyString.length; j < len; j++) {
                ks.push(keyString.charCodeAt(j));
            }
            keyCode = ks;
        }
        var keyArray = Ext.isArray(keyCode);

        var handler = function (e) {
            if (this.checkModifiers(config, e)) {
                var k = e.getKey();
                if (keyArray) {
                    for (var i = 0, len = keyCode.length; i < len; i++) {
                        if (keyCode[i] == k) {
                            if (this.stopEvent) {
                                e.stopEvent();
                            }
                            fn.call(scope || window, k, e);
                            return;
                        }
                    }
                } else {
                    if (k == keyCode) {
                        if (this.stopEvent) {
                            e.stopEvent();
                        }
                        fn.call(scope || window, k, e);
                    }
                }
            }
        };
        this.bindings.push(handler);
    },


    checkModifiers: function (config, e) {
        var val, key, keys = ['shift', 'ctrl', 'alt'];
        for (var i = 0, len = keys.length; i < len; ++i) {
            key = keys[i];
            val = config[key];
            if (!(val === undefined || (val === e[key + 'Key']))) {
                return false;
            }
        }
        return true;
    },


    on: function (key, fn, scope) {
        var keyCode, shift, ctrl, alt;
        if (typeof key == "object" && !Ext.isArray(key)) {
            keyCode = key.key;
            shift = key.shift;
            ctrl = key.ctrl;
            alt = key.alt;
        } else {
            keyCode = key;
        }
        this.addBinding({
            key: keyCode,
            shift: shift,
            ctrl: ctrl,
            alt: alt,
            fn: fn,
            scope: scope
        });
    },


    handleKeyDown: function (e) {
        if (this.enabled) {
            var b = this.bindings;
            for (var i = 0, len = b.length; i < len; i++) {
                b[i].call(this, e);
            }
        }
    },


    isEnabled: function () {
        return this.enabled;
    },


    enable: function () {
        if (!this.enabled) {
            this.el.on(this.eventName, this.handleKeyDown, this);
            this.enabled = true;
        }
    },


    disable: function () {
        if (this.enabled) {
            this.el.removeListener(this.eventName, this.handleKeyDown, this);
            this.enabled = false;
        }
    },


    setDisabled: function (disabled) {
        this[disabled ? "disable" : "enable"]();
    }
};
Ext.util.TextMetrics = function () {
    var shared;
    return {

        measure: function (el, text, fixedWidth) {
            if (!shared) {
                shared = Ext.util.TextMetrics.Instance(el, fixedWidth);
            }
            shared.bind(el);
            shared.setFixedWidth(fixedWidth || 'auto');
            return shared.getSize(text);
        },


        createInstance: function (el, fixedWidth) {
            return Ext.util.TextMetrics.Instance(el, fixedWidth);
        }
    };
} ();

Ext.util.TextMetrics.Instance = function (bindTo, fixedWidth) {
    var ml = new Ext.Element(document.createElement('div'));
    document.body.appendChild(ml.dom);
    ml.position('absolute');
    ml.setLeftTop(-1000, -1000);
    ml.hide();

    if (fixedWidth) {
        ml.setWidth(fixedWidth);
    }

    var instance = {

        getSize: function (text) {
            ml.update(text);
            var s = ml.getSize();
            ml.update('');
            return s;
        },


        bind: function (el) {
            ml.setStyle(
                Ext.fly(el).getStyles('font-size', 'font-style', 'font-weight', 'font-family', 'line-height', 'text-transform', 'letter-spacing')
            );
        },


        setFixedWidth: function (width) {
            ml.setWidth(width);
        },


        getWidth: function (text) {
            ml.dom.style.width = 'auto';
            return this.getSize(text).width;
        },


        getHeight: function (text) {
            return this.getSize(text).height;
        }
    };

    instance.bind(bindTo);

    return instance;
};

Ext.Element.addMethods({

    getTextWidth: function (text, min, max) {
        return (Ext.util.TextMetrics.measure(this.dom, Ext.value(text, this.dom.innerHTML, true)).width).constrain(min || 0, max || 1000000);
    }
});

Ext.util.Cookies = {

    set: function (name, value) {
        var argv = arguments;
        var argc = arguments.length;
        var expires = (argc > 2) ? argv[2] : null;
        var path = (argc > 3) ? argv[3] : '/';
        var domain = (argc > 4) ? argv[4] : null;
        var secure = (argc > 5) ? argv[5] : false;
        document.cookie = name + "=" + escape(value) + ((expires === null) ? "" : ("; expires=" + expires.toGMTString())) + ((path === null) ? "" : ("; path=" + path)) + ((domain === null) ? "" : ("; domain=" + domain)) + ((secure === true) ? "; secure" : "");
    },


    get: function (name) {
        var arg = name + "=";
        var alen = arg.length;
        var clen = document.cookie.length;
        var i = 0;
        var j = 0;
        while (i < clen) {
            j = i + alen;
            if (document.cookie.substring(i, j) == arg) {
                return Ext.util.Cookies.getCookieVal(j);
            }
            i = document.cookie.indexOf(" ", i) + 1;
            if (i === 0) {
                break;
            }
        }
        return null;
    },


    clear: function (name) {
        if (Ext.util.Cookies.get(name)) {
            document.cookie = name + "=" + "; expires=Thu, 01-Jan-70 00:00:01 GMT";
        }
    },

    getCookieVal: function (offset) {
        var endstr = document.cookie.indexOf(";", offset);
        if (endstr == -1) {
            endstr = document.cookie.length;
        }
        return unescape(document.cookie.substring(offset, endstr));
    }
};
Ext.handleError = function (e) {
    throw e;
};


Ext.Error = function (message) {

    this.message = (this.lang[message]) ? this.lang[message] : message;
};

Ext.Error.prototype = new Error();
Ext.apply(Ext.Error.prototype, {

    lang: {},

    name: 'Ext.Error',

    getName: function () {
        return this.name;
    },

    getMessage: function () {
        return this.message;
    },

    toJson: function () {
        return Ext.encode(this);
    }
});

Ext.ComponentMgr = function () {
    var all = new Ext.util.MixedCollection();
    var types = {};
    var ptypes = {};

    return {

        register: function (c) {
            all.add(c);
        },


        unregister: function (c) {
            all.remove(c);
        },


        get: function (id) {
            return all.get(id);
        },


        onAvailable: function (id, fn, scope) {
            all.on("add", function (index, o) {
                if (o.id == id) {
                    fn.call(scope || o, o);
                    all.un("add", fn, scope);
                }
            });
        },


        all: all,


        types: types,


        ptypes: ptypes,


        isRegistered: function (xtype) {
            return types[xtype] !== undefined;
        },


        isPluginRegistered: function (ptype) {
            return ptypes[ptype] !== undefined;
        },


        registerType: function (xtype, cls) {
            types[xtype] = cls;
            cls.xtype = xtype;
        },


        create: function (config, defaultType) {
            return config.render ? config : new types[config.xtype || defaultType](config);
        },


        registerPlugin: function (ptype, cls) {
            ptypes[ptype] = cls;
            cls.ptype = ptype;
        },


        createPlugin: function (config, defaultType) {
            var PluginCls = ptypes[config.ptype || defaultType];
            if (PluginCls.init) {
                return PluginCls;
            } else {
                return new PluginCls(config);
            }
        }
    };
} ();


Ext.reg = Ext.ComponentMgr.registerType;

Ext.preg = Ext.ComponentMgr.registerPlugin;

Ext.create = Ext.ComponentMgr.create;
Ext.Component = function (config) {
    config = config || {};
    if (config.initialConfig) {
        if (config.isAction) {
            this.baseAction = config;
        }
        config = config.initialConfig;
    } else if (config.tagName || config.dom || Ext.isString(config)) {
        config = { applyTo: config, id: config.id || config };
    }


    this.initialConfig = config;

    Ext.apply(this, config);
    this.addEvents(

        'added',

        'disable',

        'enable',

        'beforeshow',

        'show',

        'beforehide',

        'hide',

        'removed',

        'beforerender',

        'render',

        'afterrender',

        'beforedestroy',

        'destroy',

        'beforestaterestore',

        'staterestore',

        'beforestatesave',

        'statesave'
    );
    this.getId();
    Ext.ComponentMgr.register(this);
    Ext.Component.superclass.constructor.call(this);

    if (this.baseAction) {
        this.baseAction.addComponent(this);
    }

    this.initComponent();

    if (this.plugins) {
        if (Ext.isArray(this.plugins)) {
            for (var i = 0, len = this.plugins.length; i < len; i++) {
                this.plugins[i] = this.initPlugin(this.plugins[i]);
            }
        } else {
            this.plugins = this.initPlugin(this.plugins);
        }
    }

    if (this.stateful !== false) {
        this.initState();
    }

    if (this.applyTo) {
        this.applyToMarkup(this.applyTo);
        delete this.applyTo;
    } else if (this.renderTo) {
        this.render(this.renderTo);
        delete this.renderTo;
    }
};


Ext.Component.AUTO_ID = 1000;

Ext.extend(Ext.Component, Ext.util.Observable, {

















    disabled: false,

    hidden: false,







    autoEl: 'div',


    disabledClass: 'x-item-disabled',

    allowDomMove: true,

    autoShow: false,

    hideMode: 'display',

    hideParent: false,





    rendered: false,







    tplWriteMode: 'overwrite',




    bubbleEvents: [],



    ctype: 'Ext.Component',


    actionMode: 'el',


    getActionEl: function () {
        return this[this.actionMode];
    },

    initPlugin: function (p) {
        if (p.ptype && !Ext.isFunction(p.init)) {
            p = Ext.ComponentMgr.createPlugin(p);
        } else if (Ext.isString(p)) {
            p = Ext.ComponentMgr.createPlugin({
                ptype: p
            });
        }
        p.init(this);
        return p;
    },


    initComponent: function () {

        if (this.listeners) {
            this.on(this.listeners);
            delete this.listeners;
        }
        this.enableBubble(this.bubbleEvents);
    },


    render: function (container, position) {
        if (!this.rendered && this.fireEvent('beforerender', this) !== false) {
            if (!container && this.el) {
                this.el = Ext.get(this.el);
                container = this.el.dom.parentNode;
                this.allowDomMove = false;
            }
            this.container = Ext.get(container);
            if (this.ctCls) {
                this.container.addClass(this.ctCls);
            }
            this.rendered = true;
            if (position !== undefined) {
                if (Ext.isNumber(position)) {
                    position = this.container.dom.childNodes[position];
                } else {
                    position = Ext.getDom(position);
                }
            }
            this.onRender(this.container, position || null);
            if (this.autoShow) {
                this.el.removeClass(['x-hidden', 'x-hide-' + this.hideMode]);
            }
            if (this.cls) {
                this.el.addClass(this.cls);
                delete this.cls;
            }
            if (this.style) {
                this.el.applyStyles(this.style);
                delete this.style;
            }
            if (this.overCls) {
                this.el.addClassOnOver(this.overCls);
            }
            this.fireEvent('render', this);




            var contentTarget = this.getContentTarget();
            if (this.html) {
                contentTarget.update(Ext.DomHelper.markup(this.html));
                delete this.html;
            }
            if (this.contentEl) {
                var ce = Ext.getDom(this.contentEl);
                Ext.fly(ce).removeClass(['x-hidden', 'x-hide-display']);
                contentTarget.appendChild(ce);
            }
            if (this.tpl) {
                if (!this.tpl.compile) {
                    this.tpl = new Ext.XTemplate(this.tpl);
                }
                if (this.data) {
                    this.tpl[this.tplWriteMode](contentTarget, this.data);
                    delete this.data;
                }
            }
            this.afterRender(this.container);


            if (this.hidden) {

                this.doHide();
            }
            if (this.disabled) {

                this.disable(true);
            }

            if (this.stateful !== false) {
                this.initStateEvents();
            }
            this.fireEvent('afterrender', this);
        }
        return this;
    },



    update: function (htmlOrData, loadScripts, cb) {
        var contentTarget = this.getContentTarget();
        if (this.tpl && typeof htmlOrData !== "string") {
            this.tpl[this.tplWriteMode](contentTarget, htmlOrData || {});
        } else {
            var html = Ext.isObject(htmlOrData) ? Ext.DomHelper.markup(htmlOrData) : htmlOrData;
            contentTarget.update(html, loadScripts, cb);
        }
    },



    onAdded: function (container, pos) {
        this.ownerCt = container;
        this.initRef();
        this.fireEvent('added', this, container, pos);
    },


    onRemoved: function () {
        this.removeRef();
        this.fireEvent('removed', this, this.ownerCt);
        delete this.ownerCt;
    },


    initRef: function () {

        if (this.ref && !this.refOwner) {
            var levels = this.ref.split('/'),
                last = levels.length,
                i = 0,
                t = this;

            while (t && i < last) {
                t = t.ownerCt;
                ++i;
            }
            if (t) {
                t[this.refName = levels[--i]] = this;

                this.refOwner = t;
            }
        }
    },

    removeRef: function () {
        if (this.refOwner && this.refName) {
            delete this.refOwner[this.refName];
            delete this.refOwner;
        }
    },


    initState: function () {
        if (Ext.state.Manager) {
            var id = this.getStateId();
            if (id) {
                var state = Ext.state.Manager.get(id);
                if (state) {
                    if (this.fireEvent('beforestaterestore', this, state) !== false) {
                        this.applyState(Ext.apply({}, state));
                        this.fireEvent('staterestore', this, state);
                    }
                }
            }
        }
    },


    getStateId: function () {
        return this.stateId || ((/^(ext-comp-|ext-gen)/).test(String(this.id)) ? null : this.id);
    },


    initStateEvents: function () {
        if (this.stateEvents) {
            for (var i = 0, e; e = this.stateEvents[i]; i++) {
                this.on(e, this.saveState, this, { delay: 100 });
            }
        }
    },


    applyState: function (state) {
        if (state) {
            Ext.apply(this, state);
        }
    },


    getState: function () {
        return null;
    },


    saveState: function () {
        if (Ext.state.Manager && this.stateful !== false) {
            var id = this.getStateId();
            if (id) {
                var state = this.getState();
                if (this.fireEvent('beforestatesave', this, state) !== false) {
                    Ext.state.Manager.set(id, state);
                    this.fireEvent('statesave', this, state);
                }
            }
        }
    },


    applyToMarkup: function (el) {
        this.allowDomMove = false;
        this.el = Ext.get(el);
        this.render(this.el.dom.parentNode);
    },


    addClass: function (cls) {
        if (this.el) {
            this.el.addClass(cls);
        } else {
            this.cls = this.cls ? this.cls + ' ' + cls : cls;
        }
        return this;
    },


    removeClass: function (cls) {
        if (this.el) {
            this.el.removeClass(cls);
        } else if (this.cls) {
            this.cls = this.cls.split(' ').remove(cls).join(' ');
        }
        return this;
    },



    onRender: function (ct, position) {
        if (!this.el && this.autoEl) {
            if (Ext.isString(this.autoEl)) {
                this.el = document.createElement(this.autoEl);
            } else {
                var div = document.createElement('div');
                Ext.DomHelper.overwrite(div, this.autoEl);
                this.el = div.firstChild;
            }
            if (!this.el.id) {
                this.el.id = this.getId();
            }
        }
        if (this.el) {
            this.el = Ext.get(this.el);
            if (this.allowDomMove !== false) {
                ct.dom.insertBefore(this.el.dom, position);
                if (div) {
                    Ext.removeNode(div);
                    div = null;
                }
            }
        }
    },


    getAutoCreate: function () {
        var cfg = Ext.isObject(this.autoCreate) ?
                      this.autoCreate : Ext.apply({}, this.defaultAutoCreate);
        if (this.id && !cfg.id) {
            cfg.id = this.id;
        }
        return cfg;
    },


    afterRender: Ext.emptyFn,


    destroy: function () {
        if (!this.isDestroyed) {
            if (this.fireEvent('beforedestroy', this) !== false) {
                this.destroying = true;
                this.beforeDestroy();
                if (this.ownerCt && this.ownerCt.remove) {
                    this.ownerCt.remove(this, false);
                }
                if (this.rendered) {
                    this.el.remove();
                    if (this.actionMode == 'container' || this.removeMode == 'container') {
                        this.container.remove();
                    }
                }

                if (this.focusTask && this.focusTask.cancel) {
                    this.focusTask.cancel();
                }
                this.onDestroy();
                Ext.ComponentMgr.unregister(this);
                this.fireEvent('destroy', this);
                this.purgeListeners();
                this.destroying = false;
                this.isDestroyed = true;
            }
        }
    },

    deleteMembers: function () {
        var args = arguments;
        for (var i = 0, len = args.length; i < len; ++i) {
            delete this[args[i]];
        }
    },


    beforeDestroy: Ext.emptyFn,


    onDestroy: Ext.emptyFn,


    getEl: function () {
        return this.el;
    },


    getContentTarget: function () {
        return this.el;
    },


    getId: function () {
        return this.id || (this.id = 'ext-comp-' + (++Ext.Component.AUTO_ID));
    },


    getItemId: function () {
        return this.itemId || this.getId();
    },


    focus: function (selectText, delay) {
        if (delay) {
            this.focusTask = new Ext.util.DelayedTask(this.focus, this, [selectText, false]);
            this.focusTask.delay(Ext.isNumber(delay) ? delay : 10);
            return this;
        }
        if (this.rendered && !this.isDestroyed) {
            this.el.focus();
            if (selectText === true) {
                this.el.dom.select();
            }
        }
        return this;
    },


    blur: function () {
        if (this.rendered) {
            this.el.blur();
        }
        return this;
    },


    disable: function (silent) {
        if (this.rendered) {
            this.onDisable();
        }
        this.disabled = true;
        if (silent !== true) {
            this.fireEvent('disable', this);
        }
        return this;
    },


    onDisable: function () {
        this.getActionEl().addClass(this.disabledClass);
        this.el.dom.disabled = true;
    },


    enable: function () {
        if (this.rendered) {
            this.onEnable();
        }
        this.disabled = false;
        this.fireEvent('enable', this);
        return this;
    },


    onEnable: function () {
        this.getActionEl().removeClass(this.disabledClass);
        this.el.dom.disabled = false;
    },


    setDisabled: function (disabled) {
        return this[disabled ? 'disable' : 'enable']();
    },


    show: function () {
        if (this.fireEvent('beforeshow', this) !== false) {
            this.hidden = false;
            if (this.autoRender) {
                this.render(Ext.isBoolean(this.autoRender) ? Ext.getBody() : this.autoRender);
            }
            if (this.rendered) {
                this.onShow();
            }
            this.fireEvent('show', this);
        }
        return this;
    },


    onShow: function () {
        this.getVisibilityEl().removeClass('x-hide-' + this.hideMode);
    },


    hide: function () {
        if (this.fireEvent('beforehide', this) !== false) {
            this.doHide();
            this.fireEvent('hide', this);
        }
        return this;
    },


    doHide: function () {
        this.hidden = true;
        if (this.rendered) {
            this.onHide();
        }
    },


    onHide: function () {
        this.getVisibilityEl().addClass('x-hide-' + this.hideMode);
    },


    getVisibilityEl: function () {
        return this.hideParent ? this.container : this.getActionEl();
    },


    setVisible: function (visible) {
        return this[visible ? 'show' : 'hide']();
    },


    isVisible: function () {
        return this.rendered && this.getVisibilityEl().isVisible();
    },


    cloneConfig: function (overrides) {
        overrides = overrides || {};
        var id = overrides.id || Ext.id();
        var cfg = Ext.applyIf(overrides, this.initialConfig);
        cfg.id = id;
        return new this.constructor(cfg);
    },


    getXType: function () {
        return this.constructor.xtype;
    },


    isXType: function (xtype, shallow) {

        if (Ext.isFunction(xtype)) {
            xtype = xtype.xtype;
        } else if (Ext.isObject(xtype)) {
            xtype = xtype.constructor.xtype;
        }

        return !shallow ? ('/' + this.getXTypes() + '/').indexOf('/' + xtype + '/') != -1 : this.constructor.xtype == xtype;
    },


    getXTypes: function () {
        var tc = this.constructor;
        if (!tc.xtypes) {
            var c = [], sc = this;
            while (sc && sc.constructor.xtype) {
                c.unshift(sc.constructor.xtype);
                sc = sc.constructor.superclass;
            }
            tc.xtypeChain = c;
            tc.xtypes = c.join('/');
        }
        return tc.xtypes;
    },


    findParentBy: function (fn) {
        for (var p = this.ownerCt; (p != null) && !fn(p, this); p = p.ownerCt);
        return p || null;
    },


    findParentByType: function (xtype, shallow) {
        return this.findParentBy(function (c) {
            return c.isXType(xtype, shallow);
        });
    },


    bubble: function (fn, scope, args) {
        var p = this;
        while (p) {
            if (fn.apply(scope || p, args || [p]) === false) {
                break;
            }
            p = p.ownerCt;
        }
        return this;
    },


    getPositionEl: function () {
        return this.positionEl || this.el;
    },


    purgeListeners: function () {
        Ext.Component.superclass.purgeListeners.call(this);
        if (this.mons) {
            this.on('beforedestroy', this.clearMons, this, { single: true });
        }
    },


    clearMons: function () {
        Ext.each(this.mons, function (m) {
            m.item.un(m.ename, m.fn, m.scope);
        }, this);
        this.mons = [];
    },


    createMons: function () {
        if (!this.mons) {
            this.mons = [];
            this.on('beforedestroy', this.clearMons, this, { single: true });
        }
    },


    mon: function (item, ename, fn, scope, opt) {
        this.createMons();
        if (Ext.isObject(ename)) {
            var propRe = /^(?:scope|delay|buffer|single|stopEvent|preventDefault|stopPropagation|normalized|args|delegate)$/;

            var o = ename;
            for (var e in o) {
                if (propRe.test(e)) {
                    continue;
                }
                if (Ext.isFunction(o[e])) {

                    this.mons.push({
                        item: item, ename: e, fn: o[e], scope: o.scope
                    });
                    item.on(e, o[e], o.scope, o);
                } else {

                    this.mons.push({
                        item: item, ename: e, fn: o[e], scope: o.scope
                    });
                    item.on(e, o[e]);
                }
            }
            return;
        }

        this.mons.push({
            item: item, ename: ename, fn: fn, scope: scope
        });
        item.on(ename, fn, scope, opt);
    },


    mun: function (item, ename, fn, scope) {
        var found, mon;
        this.createMons();
        for (var i = 0, len = this.mons.length; i < len; ++i) {
            mon = this.mons[i];
            if (item === mon.item && ename == mon.ename && fn === mon.fn && scope === mon.scope) {
                this.mons.splice(i, 1);
                item.un(ename, fn, scope);
                found = true;
                break;
            }
        }
        return found;
    },


    nextSibling: function () {
        if (this.ownerCt) {
            var index = this.ownerCt.items.indexOf(this);
            if (index != -1 && index + 1 < this.ownerCt.items.getCount()) {
                return this.ownerCt.items.itemAt(index + 1);
            }
        }
        return null;
    },


    previousSibling: function () {
        if (this.ownerCt) {
            var index = this.ownerCt.items.indexOf(this);
            if (index > 0) {
                return this.ownerCt.items.itemAt(index - 1);
            }
        }
        return null;
    },


    getBubbleTarget: function () {
        return this.ownerCt;
    }
});

Ext.reg('component', Ext.Component);

Ext.Action = Ext.extend(Object, {








    constructor: function (config) {
        this.initialConfig = config;
        this.itemId = config.itemId = (config.itemId || config.id || Ext.id());
        this.items = [];
    },


    isAction: true,


    setText: function (text) {
        this.initialConfig.text = text;
        this.callEach('setText', [text]);
    },


    getText: function () {
        return this.initialConfig.text;
    },


    setIconClass: function (cls) {
        this.initialConfig.iconCls = cls;
        this.callEach('setIconClass', [cls]);
    },


    getIconClass: function () {
        return this.initialConfig.iconCls;
    },


    setDisabled: function (v) {
        this.initialConfig.disabled = v;
        this.callEach('setDisabled', [v]);
    },


    enable: function () {
        this.setDisabled(false);
    },


    disable: function () {
        this.setDisabled(true);
    },


    isDisabled: function () {
        return this.initialConfig.disabled;
    },


    setHidden: function (v) {
        this.initialConfig.hidden = v;
        this.callEach('setVisible', [!v]);
    },


    show: function () {
        this.setHidden(false);
    },


    hide: function () {
        this.setHidden(true);
    },


    isHidden: function () {
        return this.initialConfig.hidden;
    },


    setHandler: function (fn, scope) {
        this.initialConfig.handler = fn;
        this.initialConfig.scope = scope;
        this.callEach('setHandler', [fn, scope]);
    },


    each: function (fn, scope) {
        Ext.each(this.items, fn, scope);
    },


    callEach: function (fnName, args) {
        var cs = this.items;
        for (var i = 0, len = cs.length; i < len; i++) {
            cs[i][fnName].apply(cs[i], args);
        }
    },


    addComponent: function (comp) {
        this.items.push(comp);
        comp.on('destroy', this.removeComponent, this);
    },


    removeComponent: function (comp) {
        this.items.remove(comp);
    },


    execute: function () {
        this.initialConfig.handler.apply(this.initialConfig.scope || window, arguments);
    }
});

(function () {
    Ext.Layer = function (config, existingEl) {
        config = config || {};
        var dh = Ext.DomHelper,
        cp = config.parentEl, pel = cp ? Ext.getDom(cp) : document.body;

        if (existingEl) {
            this.dom = Ext.getDom(existingEl);
        }
        if (!this.dom) {
            var o = config.dh || { tag: 'div', cls: 'x-layer' };
            this.dom = dh.append(pel, o);
        }
        if (config.cls) {
            this.addClass(config.cls);
        }
        this.constrain = config.constrain !== false;
        this.setVisibilityMode(Ext.Element.VISIBILITY);
        if (config.id) {
            this.id = this.dom.id = config.id;
        } else {
            this.id = Ext.id(this.dom);
        }
        this.zindex = config.zindex || this.getZIndex();
        this.position('absolute', this.zindex);
        if (config.shadow) {
            this.shadowOffset = config.shadowOffset || 4;
            this.shadow = new Ext.Shadow({
                offset: this.shadowOffset,
                mode: config.shadow
            });
        } else {
            this.shadowOffset = 0;
        }
        this.useShim = config.shim !== false && Ext.useShims;
        this.useDisplay = config.useDisplay;
        this.hide();
    };

    var supr = Ext.Element.prototype;


    var shims = [];

    Ext.extend(Ext.Layer, Ext.Element, {

        getZIndex: function () {
            return this.zindex || parseInt((this.getShim() || this).getStyle('z-index'), 10) || 11000;
        },

        getShim: function () {
            if (!this.useShim) {
                return null;
            }
            if (this.shim) {
                return this.shim;
            }
            var shim = shims.shift();
            if (!shim) {
                shim = this.createShim();
                shim.enableDisplayMode('block');
                shim.dom.style.display = 'none';
                shim.dom.style.visibility = 'visible';
            }
            var pn = this.dom.parentNode;
            if (shim.dom.parentNode != pn) {
                pn.insertBefore(shim.dom, this.dom);
            }
            shim.setStyle('z-index', this.getZIndex() - 2);
            this.shim = shim;
            return shim;
        },

        hideShim: function () {
            if (this.shim) {
                this.shim.setDisplayed(false);
                shims.push(this.shim);
                delete this.shim;
            }
        },

        disableShadow: function () {
            if (this.shadow) {
                this.shadowDisabled = true;
                this.shadow.hide();
                this.lastShadowOffset = this.shadowOffset;
                this.shadowOffset = 0;
            }
        },

        enableShadow: function (show) {
            if (this.shadow) {
                this.shadowDisabled = false;
                this.shadowOffset = this.lastShadowOffset;
                delete this.lastShadowOffset;
                if (show) {
                    this.sync(true);
                }
            }
        },




        sync: function (doShow) {
            var shadow = this.shadow;
            if (!this.updating && this.isVisible() && (shadow || this.useShim)) {
                var shim = this.getShim(),
                w = this.getWidth(),
                h = this.getHeight(),
                l = this.getLeft(true),
                t = this.getTop(true);

                if (shadow && !this.shadowDisabled) {
                    if (doShow && !shadow.isVisible()) {
                        shadow.show(this);
                    } else {
                        shadow.realign(l, t, w, h);
                    }
                    if (shim) {
                        if (doShow) {
                            shim.show();
                        }

                        var shadowAdj = shadow.el.getXY(), shimStyle = shim.dom.style,
                        shadowSize = shadow.el.getSize();
                        shimStyle.left = (shadowAdj[0]) + 'px';
                        shimStyle.top = (shadowAdj[1]) + 'px';
                        shimStyle.width = (shadowSize.width) + 'px';
                        shimStyle.height = (shadowSize.height) + 'px';
                    }
                } else if (shim) {
                    if (doShow) {
                        shim.show();
                    }
                    shim.setSize(w, h);
                    shim.setLeftTop(l, t);
                }
            }
        },


        destroy: function () {
            this.hideShim();
            if (this.shadow) {
                this.shadow.hide();
            }
            this.removeAllListeners();
            Ext.removeNode(this.dom);
            delete this.dom;
        },

        remove: function () {
            this.destroy();
        },


        beginUpdate: function () {
            this.updating = true;
        },


        endUpdate: function () {
            this.updating = false;
            this.sync(true);
        },


        hideUnders: function (negOffset) {
            if (this.shadow) {
                this.shadow.hide();
            }
            this.hideShim();
        },


        constrainXY: function () {
            if (this.constrain) {
                var vw = Ext.lib.Dom.getViewWidth(),
                vh = Ext.lib.Dom.getViewHeight();
                var s = Ext.getDoc().getScroll();

                var xy = this.getXY();
                var x = xy[0], y = xy[1];
                var so = this.shadowOffset;
                var w = this.dom.offsetWidth + so, h = this.dom.offsetHeight + so;

                var moved = false;

                if ((x + w) > vw + s.left) {
                    x = vw - w - so;
                    moved = true;
                }
                if ((y + h) > vh + s.top) {
                    y = vh - h - so;
                    moved = true;
                }

                if (x < s.left) {
                    x = s.left;
                    moved = true;
                }
                if (y < s.top) {
                    y = s.top;
                    moved = true;
                }
                if (moved) {
                    if (this.avoidY) {
                        var ay = this.avoidY;
                        if (y <= ay && (y + h) >= ay) {
                            y = ay - h - 5;
                        }
                    }
                    xy = [x, y];
                    this.storeXY(xy);
                    supr.setXY.call(this, xy);
                    this.sync();
                }
            }
            return this;
        },

        getConstrainOffset: function () {
            return this.shadowOffset;
        },

        isVisible: function () {
            return this.visible;
        },


        showAction: function () {
            this.visible = true;
            if (this.useDisplay === true) {
                this.setDisplayed('');
            } else if (this.lastXY) {
                supr.setXY.call(this, this.lastXY);
            } else if (this.lastLT) {
                supr.setLeftTop.call(this, this.lastLT[0], this.lastLT[1]);
            }
        },


        hideAction: function () {
            this.visible = false;
            if (this.useDisplay === true) {
                this.setDisplayed(false);
            } else {
                this.setLeftTop(-10000, -10000);
            }
        },


        setVisible: function (v, a, d, c, e) {
            if (v) {
                this.showAction();
            }
            if (a && v) {
                var cb = function () {
                    this.sync(true);
                    if (c) {
                        c();
                    }
                } .createDelegate(this);
                supr.setVisible.call(this, true, true, d, cb, e);
            } else {
                if (!v) {
                    this.hideUnders(true);
                }
                var cb = c;
                if (a) {
                    cb = function () {
                        this.hideAction();
                        if (c) {
                            c();
                        }
                    } .createDelegate(this);
                }
                supr.setVisible.call(this, v, a, d, cb, e);
                if (v) {
                    this.sync(true);
                } else if (!a) {
                    this.hideAction();
                }
            }
            return this;
        },

        storeXY: function (xy) {
            delete this.lastLT;
            this.lastXY = xy;
        },

        storeLeftTop: function (left, top) {
            delete this.lastXY;
            this.lastLT = [left, top];
        },


        beforeFx: function () {
            this.beforeAction();
            return Ext.Layer.superclass.beforeFx.apply(this, arguments);
        },


        afterFx: function () {
            Ext.Layer.superclass.afterFx.apply(this, arguments);
            this.sync(this.isVisible());
        },


        beforeAction: function () {
            if (!this.updating && this.shadow) {
                this.shadow.hide();
            }
        },


        setLeft: function (left) {
            this.storeLeftTop(left, this.getTop(true));
            supr.setLeft.apply(this, arguments);
            this.sync();
            return this;
        },

        setTop: function (top) {
            this.storeLeftTop(this.getLeft(true), top);
            supr.setTop.apply(this, arguments);
            this.sync();
            return this;
        },

        setLeftTop: function (left, top) {
            this.storeLeftTop(left, top);
            supr.setLeftTop.apply(this, arguments);
            this.sync();
            return this;
        },

        setXY: function (xy, a, d, c, e) {
            this.fixDisplay();
            this.beforeAction();
            this.storeXY(xy);
            var cb = this.createCB(c);
            supr.setXY.call(this, xy, a, d, cb, e);
            if (!a) {
                cb();
            }
            return this;
        },


        createCB: function (c) {
            var el = this;
            return function () {
                el.constrainXY();
                el.sync(true);
                if (c) {
                    c();
                }
            };
        },


        setX: function (x, a, d, c, e) {
            this.setXY([x, this.getY()], a, d, c, e);
            return this;
        },


        setY: function (y, a, d, c, e) {
            this.setXY([this.getX(), y], a, d, c, e);
            return this;
        },


        setSize: function (w, h, a, d, c, e) {
            this.beforeAction();
            var cb = this.createCB(c);
            supr.setSize.call(this, w, h, a, d, cb, e);
            if (!a) {
                cb();
            }
            return this;
        },


        setWidth: function (w, a, d, c, e) {
            this.beforeAction();
            var cb = this.createCB(c);
            supr.setWidth.call(this, w, a, d, cb, e);
            if (!a) {
                cb();
            }
            return this;
        },


        setHeight: function (h, a, d, c, e) {
            this.beforeAction();
            var cb = this.createCB(c);
            supr.setHeight.call(this, h, a, d, cb, e);
            if (!a) {
                cb();
            }
            return this;
        },


        setBounds: function (x, y, w, h, a, d, c, e) {
            this.beforeAction();
            var cb = this.createCB(c);
            if (!a) {
                this.storeXY([x, y]);
                supr.setXY.call(this, [x, y]);
                supr.setSize.call(this, w, h, a, d, cb, e);
                cb();
            } else {
                supr.setBounds.call(this, x, y, w, h, a, d, cb, e);
            }
            return this;
        },


        setZIndex: function (zindex) {
            this.zindex = zindex;
            this.setStyle('z-index', zindex + 2);
            if (this.shadow) {
                this.shadow.setZIndex(zindex + 1);
            }
            if (this.shim) {
                this.shim.setStyle('z-index', zindex);
            }
            return this;
        }
    });
})();

Ext.Shadow = function (config) {
    Ext.apply(this, config);
    if (typeof this.mode != "string") {
        this.mode = this.defaultMode;
    }
    var o = this.offset,
        a = {
            h: 0
        },
        rad = Math.floor(this.offset / 2);
    switch (this.mode.toLowerCase()) {

        case "drop":
            a.w = 0;
            a.l = a.t = o;
            a.t -= 1;
            if (Ext.isIE) {
                a.l -= this.offset + rad;
                a.t -= this.offset + rad;
                a.w -= rad;
                a.h -= rad;
                a.t += 1;
            }
            break;
        case "sides":
            a.w = (o * 2);
            a.l = -o;
            a.t = o - 1;
            if (Ext.isIE) {
                a.l -= (this.offset - rad);
                a.t -= this.offset + rad;
                a.l += 1;
                a.w -= (this.offset - rad) * 2;
                a.w -= rad + 1;
                a.h -= 1;
            }
            break;
        case "frame":
            a.w = a.h = (o * 2);
            a.l = a.t = -o;
            a.t += 1;
            a.h -= 2;
            if (Ext.isIE) {
                a.l -= (this.offset - rad);
                a.t -= (this.offset - rad);
                a.l += 1;
                a.w -= (this.offset + rad + 1);
                a.h -= (this.offset + rad);
                a.h += 1;
            }
            break;
    };

    this.adjusts = a;
};

Ext.Shadow.prototype = {


    offset: 4,


    defaultMode: "drop",


    show: function (target) {
        target = Ext.get(target);
        if (!this.el) {
            this.el = Ext.Shadow.Pool.pull();
            if (this.el.dom.nextSibling != target.dom) {
                this.el.insertBefore(target);
            }
        }
        this.el.setStyle("z-index", this.zIndex || parseInt(target.getStyle("z-index"), 10) - 1);
        if (Ext.isIE) {
            this.el.dom.style.filter = "progid:DXImageTransform.Microsoft.alpha(opacity=50) progid:DXImageTransform.Microsoft.Blur(pixelradius=" + (this.offset) + ")";
        }
        this.realign(
        target.getLeft(true),
        target.getTop(true),
        target.getWidth(),
        target.getHeight()
        );
        this.el.dom.style.display = "block";
    },


    isVisible: function () {
        return this.el ? true : false;
    },


    realign: function (l, t, w, h) {
        if (!this.el) {
            return;
        }
        var a = this.adjusts,
            d = this.el.dom,
            s = d.style,
            iea = 0,
            sw = (w + a.w),
            sh = (h + a.h),
            sws = sw + "px",
            shs = sh + "px",
            cn,
            sww;
        s.left = (l + a.l) + "px";
        s.top = (t + a.t) + "px";
        if (s.width != sws || s.height != shs) {
            s.width = sws;
            s.height = shs;
            if (!Ext.isIE) {
                cn = d.childNodes;
                sww = Math.max(0, (sw - 12)) + "px";
                cn[0].childNodes[1].style.width = sww;
                cn[1].childNodes[1].style.width = sww;
                cn[2].childNodes[1].style.width = sww;
                cn[1].style.height = Math.max(0, (sh - 12)) + "px";
            }
        }
    },


    hide: function () {
        if (this.el) {
            this.el.dom.style.display = "none";
            Ext.Shadow.Pool.push(this.el);
            delete this.el;
        }
    },


    setZIndex: function (z) {
        this.zIndex = z;
        if (this.el) {
            this.el.setStyle("z-index", z);
        }
    }
};


Ext.Shadow.Pool = function () {
    var p = [],
        markup = Ext.isIE ?
            '<div class="x-ie-shadow"></div>' :
            '<div class="x-shadow"><div class="xst"><div class="xstl"></div><div class="xstc"></div><div class="xstr"></div></div><div class="xsc"><div class="xsml"></div><div class="xsmc"></div><div class="xsmr"></div></div><div class="xsb"><div class="xsbl"></div><div class="xsbc"></div><div class="xsbr"></div></div></div>';
    return {
        pull: function () {
            var sh = p.shift();
            if (!sh) {
                sh = Ext.get(Ext.DomHelper.insertHtml("beforeBegin", document.body.firstChild, markup));
                sh.autoBoxAdjust = false;
            }
            return sh;
        },

        push: function (sh) {
            p.push(sh);
        }
    };
} ();
Ext.BoxComponent = Ext.extend(Ext.Component, {




























    initComponent: function () {
        Ext.BoxComponent.superclass.initComponent.call(this);
        this.addEvents(

            'resize',

            'move'
        );
    },


    boxReady: false,

    deferHeight: false,


    setSize: function (w, h) {


        if (typeof w == 'object') {
            h = w.height;
            w = w.width;
        }
        if (Ext.isDefined(w) && Ext.isDefined(this.boxMinWidth) && (w < this.boxMinWidth)) {
            w = this.boxMinWidth;
        }
        if (Ext.isDefined(h) && Ext.isDefined(this.boxMinHeight) && (h < this.boxMinHeight)) {
            h = this.boxMinHeight;
        }
        if (Ext.isDefined(w) && Ext.isDefined(this.boxMaxWidth) && (w > this.boxMaxWidth)) {
            w = this.boxMaxWidth;
        }
        if (Ext.isDefined(h) && Ext.isDefined(this.boxMaxHeight) && (h > this.boxMaxHeight)) {
            h = this.boxMaxHeight;
        }

        if (!this.boxReady) {
            this.width = w;
            this.height = h;
            return this;
        }


        if (this.cacheSizes !== false && this.lastSize && this.lastSize.width == w && this.lastSize.height == h) {
            return this;
        }
        this.lastSize = { width: w, height: h };
        var adj = this.adjustSize(w, h),
            aw = adj.width,
            ah = adj.height,
            rz;
        if (aw !== undefined || ah !== undefined) {
            rz = this.getResizeEl();
            if (!this.deferHeight && aw !== undefined && ah !== undefined) {
                rz.setSize(aw, ah);
            } else if (!this.deferHeight && ah !== undefined) {
                rz.setHeight(ah);
            } else if (aw !== undefined) {
                rz.setWidth(aw);
            }
            this.onResize(aw, ah, w, h);
            this.fireEvent('resize', this, aw, ah, w, h);
        }
        return this;
    },


    setWidth: function (width) {
        return this.setSize(width);
    },


    setHeight: function (height) {
        return this.setSize(undefined, height);
    },


    getSize: function () {
        return this.getResizeEl().getSize();
    },


    getWidth: function () {
        return this.getResizeEl().getWidth();
    },


    getHeight: function () {
        return this.getResizeEl().getHeight();
    },


    getOuterSize: function () {
        var el = this.getResizeEl();
        return { width: el.getWidth() + el.getMargins('lr'),
            height: el.getHeight() + el.getMargins('tb')
        };
    },


    getPosition: function (local) {
        var el = this.getPositionEl();
        if (local === true) {
            return [el.getLeft(true), el.getTop(true)];
        }
        return this.xy || el.getXY();
    },


    getBox: function (local) {
        var pos = this.getPosition(local);
        var s = this.getSize();
        s.x = pos[0];
        s.y = pos[1];
        return s;
    },


    updateBox: function (box) {
        this.setSize(box.width, box.height);
        this.setPagePosition(box.x, box.y);
        return this;
    },


    getResizeEl: function () {
        return this.resizeEl || this.el;
    },


    setAutoScroll: function (scroll) {
        if (this.rendered) {
            this.getContentTarget().setOverflow(scroll ? 'auto' : '');
        }
        this.autoScroll = scroll;
        return this;
    },


    setPosition: function (x, y) {
        if (x && typeof x[1] == 'number') {
            y = x[1];
            x = x[0];
        }
        this.x = x;
        this.y = y;
        if (!this.boxReady) {
            return this;
        }
        var adj = this.adjustPosition(x, y);
        var ax = adj.x, ay = adj.y;

        var el = this.getPositionEl();
        if (ax !== undefined || ay !== undefined) {
            if (ax !== undefined && ay !== undefined) {
                el.setLeftTop(ax, ay);
            } else if (ax !== undefined) {
                el.setLeft(ax);
            } else if (ay !== undefined) {
                el.setTop(ay);
            }
            this.onPosition(ax, ay);
            this.fireEvent('move', this, ax, ay);
        }
        return this;
    },


    setPagePosition: function (x, y) {
        if (x && typeof x[1] == 'number') {
            y = x[1];
            x = x[0];
        }
        this.pageX = x;
        this.pageY = y;
        if (!this.boxReady) {
            return;
        }
        if (x === undefined || y === undefined) {
            return;
        }
        var p = this.getPositionEl().translatePoints(x, y);
        this.setPosition(p.left, p.top);
        return this;
    },


    afterRender: function () {
        Ext.BoxComponent.superclass.afterRender.call(this);
        if (this.resizeEl) {
            this.resizeEl = Ext.get(this.resizeEl);
        }
        if (this.positionEl) {
            this.positionEl = Ext.get(this.positionEl);
        }
        this.boxReady = true;
        Ext.isDefined(this.autoScroll) && this.setAutoScroll(this.autoScroll);
        this.setSize(this.width, this.height);
        if (this.x || this.y) {
            this.setPosition(this.x, this.y);
        } else if (this.pageX || this.pageY) {
            this.setPagePosition(this.pageX, this.pageY);
        }
    },


    syncSize: function () {
        delete this.lastSize;
        this.setSize(this.autoWidth ? undefined : this.getResizeEl().getWidth(), this.autoHeight ? undefined : this.getResizeEl().getHeight());
        return this;
    },


    onResize: function (adjWidth, adjHeight, rawWidth, rawHeight) {
    },


    onPosition: function (x, y) {

    },


    adjustSize: function (w, h) {
        if (this.autoWidth) {
            w = 'auto';
        }
        if (this.autoHeight) {
            h = 'auto';
        }
        return { width: w, height: h };
    },


    adjustPosition: function (x, y) {
        return { x: x, y: y };
    }
});
Ext.reg('box', Ext.BoxComponent);



Ext.Spacer = Ext.extend(Ext.BoxComponent, {
    autoEl: 'div'
});
Ext.reg('spacer', Ext.Spacer);
Ext.SplitBar = function (dragElement, resizingElement, orientation, placement, existingProxy) {


    this.el = Ext.get(dragElement, true);
    this.el.dom.unselectable = "on";

    this.resizingEl = Ext.get(resizingElement, true);


    this.orientation = orientation || Ext.SplitBar.HORIZONTAL;



    this.minSize = 0;


    this.maxSize = 2000;


    this.animate = false;


    this.useShim = false;


    this.shim = null;

    if (!existingProxy) {

        this.proxy = Ext.SplitBar.createProxy(this.orientation);
    } else {
        this.proxy = Ext.get(existingProxy).dom;
    }

    this.dd = new Ext.dd.DDProxy(this.el.dom.id, "XSplitBars", { dragElId: this.proxy.id });


    this.dd.b4StartDrag = this.onStartProxyDrag.createDelegate(this);


    this.dd.endDrag = this.onEndProxyDrag.createDelegate(this);


    this.dragSpecs = {};


    this.adapter = new Ext.SplitBar.BasicLayoutAdapter();
    this.adapter.init(this);

    if (this.orientation == Ext.SplitBar.HORIZONTAL) {

        this.placement = placement || (this.el.getX() > this.resizingEl.getX() ? Ext.SplitBar.LEFT : Ext.SplitBar.RIGHT);
        this.el.addClass("x-splitbar-h");
    } else {

        this.placement = placement || (this.el.getY() > this.resizingEl.getY() ? Ext.SplitBar.TOP : Ext.SplitBar.BOTTOM);
        this.el.addClass("x-splitbar-v");
    }

    this.addEvents(

        "resize",

        "moved",

        "beforeresize",

        "beforeapply"
    );

    Ext.SplitBar.superclass.constructor.call(this);
};

Ext.extend(Ext.SplitBar, Ext.util.Observable, {
    onStartProxyDrag: function (x, y) {
        this.fireEvent("beforeresize", this);
        this.overlay = Ext.DomHelper.append(document.body, { cls: "x-drag-overlay", html: "&#160;" }, true);
        this.overlay.unselectable();
        this.overlay.setSize(Ext.lib.Dom.getViewWidth(true), Ext.lib.Dom.getViewHeight(true));
        this.overlay.show();
        Ext.get(this.proxy).setDisplayed("block");
        var size = this.adapter.getElementSize(this);
        this.activeMinSize = this.getMinimumSize();
        this.activeMaxSize = this.getMaximumSize();
        var c1 = size - this.activeMinSize;
        var c2 = Math.max(this.activeMaxSize - size, 0);
        if (this.orientation == Ext.SplitBar.HORIZONTAL) {
            this.dd.resetConstraints();
            this.dd.setXConstraint(
                this.placement == Ext.SplitBar.LEFT ? c1 : c2,
                this.placement == Ext.SplitBar.LEFT ? c2 : c1,
                this.tickSize
            );
            this.dd.setYConstraint(0, 0);
        } else {
            this.dd.resetConstraints();
            this.dd.setXConstraint(0, 0);
            this.dd.setYConstraint(
                this.placement == Ext.SplitBar.TOP ? c1 : c2,
                this.placement == Ext.SplitBar.TOP ? c2 : c1,
                this.tickSize
            );
        }
        this.dragSpecs.startSize = size;
        this.dragSpecs.startPoint = [x, y];
        Ext.dd.DDProxy.prototype.b4StartDrag.call(this.dd, x, y);
    },


    onEndProxyDrag: function (e) {
        Ext.get(this.proxy).setDisplayed(false);
        var endPoint = Ext.lib.Event.getXY(e);
        if (this.overlay) {
            Ext.destroy(this.overlay);
            delete this.overlay;
        }
        var newSize;
        if (this.orientation == Ext.SplitBar.HORIZONTAL) {
            newSize = this.dragSpecs.startSize +
                (this.placement == Ext.SplitBar.LEFT ?
                    endPoint[0] - this.dragSpecs.startPoint[0] :
                    this.dragSpecs.startPoint[0] - endPoint[0]
                );
        } else {
            newSize = this.dragSpecs.startSize +
                (this.placement == Ext.SplitBar.TOP ?
                    endPoint[1] - this.dragSpecs.startPoint[1] :
                    this.dragSpecs.startPoint[1] - endPoint[1]
                );
        }
        newSize = Math.min(Math.max(newSize, this.activeMinSize), this.activeMaxSize);
        if (newSize != this.dragSpecs.startSize) {
            if (this.fireEvent('beforeapply', this, newSize) !== false) {
                this.adapter.setElementSize(this, newSize);
                this.fireEvent("moved", this, newSize);
                this.fireEvent("resize", this, newSize);
            }
        }
    },


    getAdapter: function () {
        return this.adapter;
    },


    setAdapter: function (adapter) {
        this.adapter = adapter;
        this.adapter.init(this);
    },


    getMinimumSize: function () {
        return this.minSize;
    },


    setMinimumSize: function (minSize) {
        this.minSize = minSize;
    },


    getMaximumSize: function () {
        return this.maxSize;
    },


    setMaximumSize: function (maxSize) {
        this.maxSize = maxSize;
    },


    setCurrentSize: function (size) {
        var oldAnimate = this.animate;
        this.animate = false;
        this.adapter.setElementSize(this, size);
        this.animate = oldAnimate;
    },


    destroy: function (removeEl) {
        Ext.destroy(this.shim, Ext.get(this.proxy));
        this.dd.unreg();
        if (removeEl) {
            this.el.remove();
        }
        this.purgeListeners();
    }
});


Ext.SplitBar.createProxy = function (dir) {
    var proxy = new Ext.Element(document.createElement("div"));
    document.body.appendChild(proxy.dom);
    proxy.unselectable();
    var cls = 'x-splitbar-proxy';
    proxy.addClass(cls + ' ' + (dir == Ext.SplitBar.HORIZONTAL ? cls + '-h' : cls + '-v'));
    return proxy.dom;
};


Ext.SplitBar.BasicLayoutAdapter = function () {
};

Ext.SplitBar.BasicLayoutAdapter.prototype = {

    init: function (s) {

    },

    getElementSize: function (s) {
        if (s.orientation == Ext.SplitBar.HORIZONTAL) {
            return s.resizingEl.getWidth();
        } else {
            return s.resizingEl.getHeight();
        }
    },


    setElementSize: function (s, newSize, onComplete) {
        if (s.orientation == Ext.SplitBar.HORIZONTAL) {
            if (!s.animate) {
                s.resizingEl.setWidth(newSize);
                if (onComplete) {
                    onComplete(s, newSize);
                }
            } else {
                s.resizingEl.setWidth(newSize, true, .1, onComplete, 'easeOut');
            }
        } else {

            if (!s.animate) {
                s.resizingEl.setHeight(newSize);
                if (onComplete) {
                    onComplete(s, newSize);
                }
            } else {
                s.resizingEl.setHeight(newSize, true, .1, onComplete, 'easeOut');
            }
        }
    }
};


Ext.SplitBar.AbsoluteLayoutAdapter = function (container) {
    this.basic = new Ext.SplitBar.BasicLayoutAdapter();
    this.container = Ext.get(container);
};

Ext.SplitBar.AbsoluteLayoutAdapter.prototype = {
    init: function (s) {
        this.basic.init(s);
    },

    getElementSize: function (s) {
        return this.basic.getElementSize(s);
    },

    setElementSize: function (s, newSize, onComplete) {
        this.basic.setElementSize(s, newSize, this.moveSplitter.createDelegate(this, [s]));
    },

    moveSplitter: function (s) {
        var yes = Ext.SplitBar;
        switch (s.placement) {
            case yes.LEFT:
                s.el.setX(s.resizingEl.getRight());
                break;
            case yes.RIGHT:
                s.el.setStyle("right", (this.container.getWidth() - s.resizingEl.getLeft()) + "px");
                break;
            case yes.TOP:
                s.el.setY(s.resizingEl.getBottom());
                break;
            case yes.BOTTOM:
                s.el.setY(s.resizingEl.getTop() - s.el.getHeight());
                break;
        }
    }
};


Ext.SplitBar.VERTICAL = 1;


Ext.SplitBar.HORIZONTAL = 2;


Ext.SplitBar.LEFT = 1;


Ext.SplitBar.RIGHT = 2;


Ext.SplitBar.TOP = 3;


Ext.SplitBar.BOTTOM = 4;

Ext.Container = Ext.extend(Ext.BoxComponent, {




    bufferResize: 50,







    autoDestroy: true,


    forceLayout: false,



    defaultType: 'panel',


    resizeEvent: 'resize',


    bubbleEvents: ['add', 'remove'],


    initComponent: function () {
        Ext.Container.superclass.initComponent.call(this);

        this.addEvents(

            'afterlayout',

            'beforeadd',

            'beforeremove',

            'add',

            'remove'
        );


        var items = this.items;
        if (items) {
            delete this.items;
            this.add(items);
        }
    },


    initItems: function () {
        if (!this.items) {
            this.items = new Ext.util.MixedCollection(false, this.getComponentId);
            this.getLayout();
        }
    },


    setLayout: function (layout) {
        if (this.layout && this.layout != layout) {
            this.layout.setContainer(null);
        }
        this.layout = layout;
        this.initItems();
        layout.setContainer(this);
    },

    afterRender: function () {


        Ext.Container.superclass.afterRender.call(this);
        if (!this.layout) {
            this.layout = 'auto';
        }
        if (Ext.isObject(this.layout) && !this.layout.layout) {
            this.layoutConfig = this.layout;
            this.layout = this.layoutConfig.type;
        }
        if (Ext.isString(this.layout)) {
            this.layout = new Ext.Container.LAYOUTS[this.layout.toLowerCase()](this.layoutConfig);
        }
        this.setLayout(this.layout);


        if (this.activeItem !== undefined && this.layout.setActiveItem) {
            var item = this.activeItem;
            delete this.activeItem;
            this.layout.setActiveItem(item);
        }


        if (!this.ownerCt) {
            this.doLayout(false, true);
        }



        if (this.monitorResize === true) {
            Ext.EventManager.onWindowResize(this.doLayout, this, [false]);
        }
    },


    getLayoutTarget: function () {
        return this.el;
    },


    getComponentId: function (comp) {
        return comp.getItemId();
    },


    add: function (comp) {
        this.initItems();
        var args = arguments.length > 1;
        if (args || Ext.isArray(comp)) {
            var result = [];
            Ext.each(args ? arguments : comp, function (c) {
                result.push(this.add(c));
            }, this);
            return result;
        }
        var c = this.lookupComponent(this.applyDefaults(comp));
        var index = this.items.length;
        if (this.fireEvent('beforeadd', this, c, index) !== false && this.onBeforeAdd(c) !== false) {
            this.items.add(c);

            c.onAdded(this, index);
            this.onAdd(c);
            this.fireEvent('add', this, c, index);
        }
        return c;
    },

    onAdd: function (c) {

    },


    onAdded: function (container, pos) {

        this.ownerCt = container;
        this.initRef();

        this.cascade(function (c) {
            c.initRef();
        });
        this.fireEvent('added', this, container, pos);
    },


    insert: function (index, comp) {
        var args = arguments,
            length = args.length,
            result = [],
            i, c;

        this.initItems();

        if (length > 2) {
            for (i = length - 1; i >= 1; --i) {
                result.push(this.insert(index, args[i]));
            }
            return result;
        }

        c = this.lookupComponent(this.applyDefaults(comp));
        index = Math.min(index, this.items.length);

        if (this.fireEvent('beforeadd', this, c, index) !== false && this.onBeforeAdd(c) !== false) {
            if (c.ownerCt == this) {
                this.items.remove(c);
            }
            this.items.insert(index, c);
            c.onAdded(this, index);
            this.onAdd(c);
            this.fireEvent('add', this, c, index);
        }

        return c;
    },


    applyDefaults: function (c) {
        var d = this.defaults;
        if (d) {
            if (Ext.isFunction(d)) {
                d = d.call(this, c);
            }
            if (Ext.isString(c)) {
                c = Ext.ComponentMgr.get(c);
                Ext.apply(c, d);
            } else if (!c.events) {
                Ext.applyIf(c, d);
            } else {
                Ext.apply(c, d);
            }
        }
        return c;
    },


    onBeforeAdd: function (item) {
        if (item.ownerCt) {
            item.ownerCt.remove(item, false);
        }
        if (this.hideBorders === true) {
            item.border = (item.border === true);
        }
    },


    remove: function (comp, autoDestroy) {
        this.initItems();
        var c = this.getComponent(comp);
        if (c && this.fireEvent('beforeremove', this, c) !== false) {
            this.doRemove(c, autoDestroy);
            this.fireEvent('remove', this, c);
        }
        return c;
    },

    onRemove: function (c) {

    },


    doRemove: function (c, autoDestroy) {
        var l = this.layout,
            hasLayout = l && this.rendered;

        if (hasLayout) {
            l.onRemove(c);
        }
        this.items.remove(c);
        c.onRemoved();
        this.onRemove(c);
        if (autoDestroy === true || (autoDestroy !== false && this.autoDestroy)) {
            c.destroy();
        }
        if (hasLayout) {
            l.afterRemove(c);
        }
    },


    removeAll: function (autoDestroy) {
        this.initItems();
        var item, rem = [], items = [];
        this.items.each(function (i) {
            rem.push(i);
        });
        for (var i = 0, len = rem.length; i < len; ++i) {
            item = rem[i];
            this.remove(item, autoDestroy);
            if (item.ownerCt !== this) {
                items.push(item);
            }
        }
        return items;
    },


    getComponent: function (comp) {
        if (Ext.isObject(comp)) {
            comp = comp.getItemId();
        }
        return this.items.get(comp);
    },


    lookupComponent: function (comp) {
        if (Ext.isString(comp)) {
            return Ext.ComponentMgr.get(comp);
        } else if (!comp.events) {
            return this.createComponent(comp);
        }
        return comp;
    },


    createComponent: function (config, defaultType) {
        if (config.render) {
            return config;
        }


        var c = Ext.create(Ext.apply({
            ownerCt: this
        }, config), defaultType || this.defaultType);
        delete c.initialConfig.ownerCt;
        delete c.ownerCt;
        return c;
    },


    canLayout: function () {
        var el = this.getVisibilityEl();
        return el && el.dom && !el.isStyle("display", "none");
    },



    doLayout: function (shallow, force) {
        var rendered = this.rendered,
            forceLayout = force || this.forceLayout;

        if (this.collapsed || !this.canLayout()) {
            this.deferLayout = this.deferLayout || !shallow;
            if (!forceLayout) {
                return;
            }
            shallow = shallow && !this.deferLayout;
        } else {
            delete this.deferLayout;
        }
        if (rendered && this.layout) {
            this.layout.layout();
        }
        if (shallow !== true && this.items) {
            var cs = this.items.items;
            for (var i = 0, len = cs.length; i < len; i++) {
                var c = cs[i];
                if (c.doLayout) {
                    c.doLayout(false, forceLayout);
                }
            }
        }
        if (rendered) {
            this.onLayout(shallow, forceLayout);
        }

        this.hasLayout = true;
        delete this.forceLayout;
    },

    onLayout: Ext.emptyFn,


    shouldBufferLayout: function () {

        var hl = this.hasLayout;
        if (this.ownerCt) {

            return hl ? !this.hasLayoutPending() : false;
        }

        return hl;
    },


    hasLayoutPending: function () {

        var pending = false;
        this.ownerCt.bubble(function (c) {
            if (c.layoutPending) {
                pending = true;
                return false;
            }
        });
        return pending;
    },

    onShow: function () {

        Ext.Container.superclass.onShow.call(this);

        if (Ext.isDefined(this.deferLayout)) {
            delete this.deferLayout;
            this.doLayout(true);
        }
    },


    getLayout: function () {
        if (!this.layout) {
            var layout = new Ext.layout.AutoLayout(this.layoutConfig);
            this.setLayout(layout);
        }
        return this.layout;
    },


    beforeDestroy: function () {
        var c;
        if (this.items) {
            while (c = this.items.first()) {
                this.doRemove(c, true);
            }
        }
        if (this.monitorResize) {
            Ext.EventManager.removeResizeListener(this.doLayout, this);
        }
        Ext.destroy(this.layout);
        Ext.Container.superclass.beforeDestroy.call(this);
    },


    cascade: function (fn, scope, args) {
        if (fn.apply(scope || this, args || [this]) !== false) {
            if (this.items) {
                var cs = this.items.items;
                for (var i = 0, len = cs.length; i < len; i++) {
                    if (cs[i].cascade) {
                        cs[i].cascade(fn, scope, args);
                    } else {
                        fn.apply(scope || cs[i], args || [cs[i]]);
                    }
                }
            }
        }
        return this;
    },


    findById: function (id) {
        var m = null,
            ct = this;
        this.cascade(function (c) {
            if (ct != c && c.id === id) {
                m = c;
                return false;
            }
        });
        return m;
    },


    findByType: function (xtype, shallow) {
        return this.findBy(function (c) {
            return c.isXType(xtype, shallow);
        });
    },


    find: function (prop, value) {
        return this.findBy(function (c) {
            return c[prop] === value;
        });
    },


    findBy: function (fn, scope) {
        var m = [], ct = this;
        this.cascade(function (c) {
            if (ct != c && fn.call(scope || c, c, ct) === true) {
                m.push(c);
            }
        });
        return m;
    },


    get: function (key) {
        return this.getComponent(key);
    }
});

Ext.Container.LAYOUTS = {};
Ext.reg('container', Ext.Container);

Ext.layout.ContainerLayout = Ext.extend(Object, {






    monitorResize: false,

    activeItem: null,

    constructor: function (config) {
        this.id = Ext.id(null, 'ext-layout-');
        Ext.apply(this, config);
    },

    type: 'container',


    IEMeasureHack: function (target, viewFlag) {
        var tChildren = target.dom.childNodes, tLen = tChildren.length, c, d = [], e, i, ret;
        for (i = 0; i < tLen; i++) {
            c = tChildren[i];
            e = Ext.get(c);
            if (e) {
                d[i] = e.getStyle('display');
                e.setStyle({ display: 'none' });
            }
        }
        ret = target ? target.getViewSize(viewFlag) : {};
        for (i = 0; i < tLen; i++) {
            c = tChildren[i];
            e = Ext.get(c);
            if (e) {
                e.setStyle({ display: d[i] });
            }
        }
        return ret;
    },


    getLayoutTargetSize: Ext.EmptyFn,


    layout: function () {
        var ct = this.container, target = ct.getLayoutTarget();
        if (!(this.hasLayout || Ext.isEmpty(this.targetCls))) {
            target.addClass(this.targetCls);
        }
        this.onLayout(ct, target);
        ct.fireEvent('afterlayout', ct, this);
    },


    onLayout: function (ct, target) {
        this.renderAll(ct, target);
    },


    isValidParent: function (c, target) {
        return target && c.getPositionEl().dom.parentNode == (target.dom || target);
    },


    renderAll: function (ct, target) {
        var items = ct.items.items, i, c, len = items.length;
        for (i = 0; i < len; i++) {
            c = items[i];
            if (c && (!c.rendered || !this.isValidParent(c, target))) {
                this.renderItem(c, i, target);
            }
        }
    },


    renderItem: function (c, position, target) {
        if (c) {
            if (!c.rendered) {
                c.render(target, position);
                this.configureItem(c);
            } else if (!this.isValidParent(c, target)) {
                if (Ext.isNumber(position)) {
                    position = target.dom.childNodes[position];
                }

                target.dom.insertBefore(c.getPositionEl().dom, position || null);
                c.container = target;
                this.configureItem(c);
            }
        }
    },



    getRenderedItems: function (ct) {
        var t = ct.getLayoutTarget(), cti = ct.items.items, len = cti.length, i, c, items = [];
        for (i = 0; i < len; i++) {
            if ((c = cti[i]).rendered && this.isValidParent(c, t) && c.shouldLayout !== false) {
                items.push(c);
            }
        };
        return items;
    },


    configureItem: function (c) {
        if (this.extraCls) {
            var t = c.getPositionEl ? c.getPositionEl() : c;
            t.addClass(this.extraCls);
        }


        if (c.doLayout && this.forceLayout) {
            c.doLayout();
        }
        if (this.renderHidden && c != this.activeItem) {
            c.hide();
        }
    },

    onRemove: function (c) {
        if (this.activeItem == c) {
            delete this.activeItem;
        }
        if (c.rendered && this.extraCls) {
            var t = c.getPositionEl ? c.getPositionEl() : c;
            t.removeClass(this.extraCls);
        }
    },

    afterRemove: function (c) {
        if (c.removeRestore) {
            c.removeMode = 'container';
            delete c.removeRestore;
        }
    },


    onResize: function () {
        var ct = this.container,
            b;
        if (ct.collapsed) {
            return;
        }
        if (b = ct.bufferResize && ct.shouldBufferLayout()) {
            if (!this.resizeTask) {
                this.resizeTask = new Ext.util.DelayedTask(this.runLayout, this);
                this.resizeBuffer = Ext.isNumber(b) ? b : 50;
            }
            ct.layoutPending = true;
            this.resizeTask.delay(this.resizeBuffer);
        } else {
            this.runLayout();
        }
    },

    runLayout: function () {
        var ct = this.container;
        this.layout();
        ct.onLayout();
        delete ct.layoutPending;
    },


    setContainer: function (ct) {

        if (this.monitorResize && ct != this.container) {
            var old = this.container;
            if (old) {
                old.un(old.resizeEvent, this.onResize, this);
            }
            if (ct) {
                ct.on(ct.resizeEvent, this.onResize, this);
            }
        }
        this.container = ct;
    },


    parseMargins: function (v) {
        if (Ext.isNumber(v)) {
            v = v.toString();
        }
        var ms = v.split(' '),
            len = ms.length;

        if (len == 1) {
            ms[1] = ms[2] = ms[3] = ms[0];
        } else if (len == 2) {
            ms[2] = ms[0];
            ms[3] = ms[1];
        } else if (len == 3) {
            ms[3] = ms[1];
        }

        return {
            top: parseInt(ms[0], 10) || 0,
            right: parseInt(ms[1], 10) || 0,
            bottom: parseInt(ms[2], 10) || 0,
            left: parseInt(ms[3], 10) || 0
        };
    },


    fieldTpl: (function () {
        var t = new Ext.Template(
            '<div class="x-form-item {itemCls}" tabIndex="-1">',
                '<label for="{id}" style="{labelStyle}" class="x-form-item-label">{label}{labelSeparator}</label>',
                '<div class="x-form-element" id="x-form-el-{id}" style="{elementStyle}">',
                '</div><div class="{clearCls}"></div>',
            '</div>'
        );
        t.disableFormats = true;
        return t.compile();
    })(),


    destroy: function () {

        if (this.resizeTask && this.resizeTask.cancel) {
            this.resizeTask.cancel();
        }
        if (!Ext.isEmpty(this.targetCls)) {
            var target = this.container.getLayoutTarget();
            if (target) {
                target.removeClass(this.targetCls);
            }
        }
    }
});
Ext.layout.AutoLayout = Ext.extend(Ext.layout.ContainerLayout, {
    type: 'auto',

    monitorResize: true,

    onLayout: function (ct, target) {
        Ext.layout.AutoLayout.superclass.onLayout.call(this, ct, target);
        var cs = this.getRenderedItems(ct), len = cs.length, i, c;
        for (i = 0; i < len; i++) {
            c = cs[i];
            if (c.doLayout) {

                c.doLayout(true);
            }
        }
    }
});

Ext.Container.LAYOUTS['auto'] = Ext.layout.AutoLayout;

Ext.layout.FitLayout = Ext.extend(Ext.layout.ContainerLayout, {

    monitorResize: true,

    type: 'fit',

    getLayoutTargetSize: function () {
        var target = this.container.getLayoutTarget();
        if (!target) {
            return {};
        }

        return target.getStyleSize();
    },


    onLayout: function (ct, target) {
        Ext.layout.FitLayout.superclass.onLayout.call(this, ct, target);
        if (!ct.collapsed) {
            this.setItemSize(this.activeItem || ct.items.itemAt(0), this.getLayoutTargetSize());
        }
    },


    setItemSize: function (item, size) {
        if (item && size.height > 0) {
            item.setSize(size);
        }
    }
});
Ext.Container.LAYOUTS['fit'] = Ext.layout.FitLayout;
Ext.layout.CardLayout = Ext.extend(Ext.layout.FitLayout, {

    deferredRender: false,


    layoutOnCardChange: false,



    renderHidden: true,

    type: 'card',


    setActiveItem: function (item) {
        var ai = this.activeItem,
            ct = this.container;
        item = ct.getComponent(item);


        if (item && ai != item) {


            if (ai) {
                ai.hide();
                if (ai.hidden !== true) {
                    return false;
                }
                ai.fireEvent('deactivate', ai);
            }

            var layout = item.doLayout && (this.layoutOnCardChange || !item.rendered);


            this.activeItem = item;



            delete item.deferLayout;


            item.show();

            this.layout();

            if (layout) {
                item.doLayout();
            }
            item.fireEvent('activate', item);
        }
    },


    renderAll: function (ct, target) {
        if (this.deferredRender) {
            this.renderItem(this.activeItem, undefined, target);
        } else {
            Ext.layout.CardLayout.superclass.renderAll.call(this, ct, target);
        }
    }
});
Ext.Container.LAYOUTS['card'] = Ext.layout.CardLayout;

Ext.layout.AnchorLayout = Ext.extend(Ext.layout.ContainerLayout, {



    monitorResize: true,

    type: 'anchor',


    defaultAnchor: '100%',

    parseAnchorRE: /^(r|right|b|bottom)$/i,


    getLayoutTargetSize: function () {
        var target = this.container.getLayoutTarget(), ret = {};
        if (target) {
            ret = target.getViewSize();




            if (Ext.isIE && Ext.isStrict && ret.width == 0) {
                ret = target.getStyleSize();
            }
            ret.width -= target.getPadding('lr');
            ret.height -= target.getPadding('tb');
        }
        return ret;
    },


    onLayout: function (container, target) {
        Ext.layout.AnchorLayout.superclass.onLayout.call(this, container, target);

        var size = this.getLayoutTargetSize(),
            containerWidth = size.width,
            containerHeight = size.height,
            overflow = target.getStyle('overflow'),
            components = this.getRenderedItems(container),
            len = components.length,
            boxes = [],
            box,
            anchorWidth,
            anchorHeight,
            component,
            anchorSpec,
            calcWidth,
            calcHeight,
            anchorsArray,
            totalHeight = 0,
            i,
            el;

        if (containerWidth < 20 && containerHeight < 20) {
            return;
        }


        if (container.anchorSize) {
            if (typeof container.anchorSize == 'number') {
                anchorWidth = container.anchorSize;
            } else {
                anchorWidth = container.anchorSize.width;
                anchorHeight = container.anchorSize.height;
            }
        } else {
            anchorWidth = container.initialConfig.width;
            anchorHeight = container.initialConfig.height;
        }

        for (i = 0; i < len; i++) {
            component = components[i];
            el = component.getPositionEl();


            if (!component.anchor && component.items && !Ext.isNumber(component.width) && !(Ext.isIE6 && Ext.isStrict)) {
                component.anchor = this.defaultAnchor;
            }

            if (component.anchor) {
                anchorSpec = component.anchorSpec;

                if (!anchorSpec) {
                    anchorsArray = component.anchor.split(' ');
                    component.anchorSpec = anchorSpec = {
                        right: this.parseAnchor(anchorsArray[0], component.initialConfig.width, anchorWidth),
                        bottom: this.parseAnchor(anchorsArray[1], component.initialConfig.height, anchorHeight)
                    };
                }
                calcWidth = anchorSpec.right ? this.adjustWidthAnchor(anchorSpec.right(containerWidth) - el.getMargins('lr'), component) : undefined;
                calcHeight = anchorSpec.bottom ? this.adjustHeightAnchor(anchorSpec.bottom(containerHeight) - el.getMargins('tb'), component) : undefined;

                if (calcWidth || calcHeight) {
                    boxes.push({
                        component: component,
                        width: calcWidth || undefined,
                        height: calcHeight || undefined
                    });
                }
            }
        }
        for (i = 0, len = boxes.length; i < len; i++) {
            box = boxes[i];
            box.component.setSize(box.width, box.height);
        }

        if (overflow && overflow != 'hidden' && !this.adjustmentPass) {
            var newTargetSize = this.getLayoutTargetSize();
            if (newTargetSize.width != size.width || newTargetSize.height != size.height) {
                this.adjustmentPass = true;
                this.onLayout(container, target);
            }
        }

        delete this.adjustmentPass;
    },


    parseAnchor: function (a, start, cstart) {
        if (a && a != 'none') {
            var last;

            if (this.parseAnchorRE.test(a)) {
                var diff = cstart - start;
                return function (v) {
                    if (v !== last) {
                        last = v;
                        return v - diff;
                    }
                };

            } else if (a.indexOf('%') != -1) {
                var ratio = parseFloat(a.replace('%', '')) * .01;
                return function (v) {
                    if (v !== last) {
                        last = v;
                        return Math.floor(v * ratio);
                    }
                };

            } else {
                a = parseInt(a, 10);
                if (!isNaN(a)) {
                    return function (v) {
                        if (v !== last) {
                            last = v;
                            return v + a;
                        }
                    };
                }
            }
        }
        return false;
    },


    adjustWidthAnchor: function (value, comp) {
        return value;
    },


    adjustHeightAnchor: function (value, comp) {
        return value;
    }


});
Ext.Container.LAYOUTS['anchor'] = Ext.layout.AnchorLayout;

Ext.layout.ColumnLayout = Ext.extend(Ext.layout.ContainerLayout, {

    monitorResize: true,

    type: 'column',

    extraCls: 'x-column',

    scrollOffset: 0,



    targetCls: 'x-column-layout-ct',

    isValidParent: function (c, target) {
        return this.innerCt && c.getPositionEl().dom.parentNode == this.innerCt.dom;
    },

    getLayoutTargetSize: function () {
        var target = this.container.getLayoutTarget(), ret;
        if (target) {
            ret = target.getViewSize();




            if (Ext.isIE && Ext.isStrict && ret.width == 0) {
                ret = target.getStyleSize();
            }

            ret.width -= target.getPadding('lr');
            ret.height -= target.getPadding('tb');
        }
        return ret;
    },

    renderAll: function (ct, target) {
        if (!this.innerCt) {


            this.innerCt = target.createChild({ cls: 'x-column-inner' });
            this.innerCt.createChild({ cls: 'x-clear' });
        }
        Ext.layout.ColumnLayout.superclass.renderAll.call(this, ct, this.innerCt);
    },


    onLayout: function (ct, target) {
        var cs = ct.items.items,
            len = cs.length,
            c,
            i,
            m,
            margins = [];

        this.renderAll(ct, target);

        var size = this.getLayoutTargetSize();

        if (size.width < 1 && size.height < 1) {
            return;
        }

        var w = size.width - this.scrollOffset,
            h = size.height,
            pw = w;

        this.innerCt.setWidth(w);




        for (i = 0; i < len; i++) {
            c = cs[i];
            m = c.getPositionEl().getMargins('lr');
            margins[i] = m;
            if (!c.columnWidth) {
                pw -= (c.getWidth() + m);
            }
        }

        pw = pw < 0 ? 0 : pw;

        for (i = 0; i < len; i++) {
            c = cs[i];
            m = margins[i];
            if (c.columnWidth) {
                c.setSize(Math.floor(c.columnWidth * pw) - m);
            }
        }



        if (Ext.isIE) {
            if (i = target.getStyle('overflow') && i != 'hidden' && !this.adjustmentPass) {
                var ts = this.getLayoutTargetSize();
                if (ts.width != size.width) {
                    this.adjustmentPass = true;
                    this.onLayout(ct, target);
                }
            }
        }
        delete this.adjustmentPass;
    }


});

Ext.Container.LAYOUTS['column'] = Ext.layout.ColumnLayout;

Ext.layout.BorderLayout = Ext.extend(Ext.layout.ContainerLayout, {

    monitorResize: true,

    rendered: false,

    type: 'border',

    targetCls: 'x-border-layout-ct',

    getLayoutTargetSize: function () {
        var target = this.container.getLayoutTarget();
        return target ? target.getViewSize() : {};
    },


    onLayout: function (ct, target) {
        var collapsed, i, c, pos, items = ct.items.items, len = items.length;
        if (!this.rendered) {
            collapsed = [];
            for (i = 0; i < len; i++) {
                c = items[i];
                pos = c.region;
                if (c.collapsed) {
                    collapsed.push(c);
                }
                c.collapsed = false;
                if (!c.rendered) {
                    c.render(target, i);
                    c.getPositionEl().addClass('x-border-panel');
                }
                this[pos] = pos != 'center' && c.split ?
                    new Ext.layout.BorderLayout.SplitRegion(this, c.initialConfig, pos) :
                    new Ext.layout.BorderLayout.Region(this, c.initialConfig, pos);
                this[pos].render(target, c);
            }
            this.rendered = true;
        }

        var size = this.getLayoutTargetSize();
        if (size.width < 20 || size.height < 20) {
            if (collapsed) {
                this.restoreCollapsed = collapsed;
            }
            return;
        } else if (this.restoreCollapsed) {
            collapsed = this.restoreCollapsed;
            delete this.restoreCollapsed;
        }

        var w = size.width, h = size.height,
            centerW = w, centerH = h, centerY = 0, centerX = 0,
            n = this.north, s = this.south, west = this.west, e = this.east, c = this.center,
            b, m, totalWidth, totalHeight;
        if (!c && Ext.layout.BorderLayout.WARN !== false) {
            throw 'No center region defined in BorderLayout ' + ct.id;
        }

        if (n && n.isVisible()) {
            b = n.getSize();
            m = n.getMargins();
            b.width = w - (m.left + m.right);
            b.x = m.left;
            b.y = m.top;
            centerY = b.height + b.y + m.bottom;
            centerH -= centerY;
            n.applyLayout(b);
        }
        if (s && s.isVisible()) {
            b = s.getSize();
            m = s.getMargins();
            b.width = w - (m.left + m.right);
            b.x = m.left;
            totalHeight = (b.height + m.top + m.bottom);
            b.y = h - totalHeight + m.top;
            centerH -= totalHeight;
            s.applyLayout(b);
        }
        if (west && west.isVisible()) {
            b = west.getSize();
            m = west.getMargins();
            b.height = centerH - (m.top + m.bottom);
            b.x = m.left;
            b.y = centerY + m.top;
            totalWidth = (b.width + m.left + m.right);
            centerX += totalWidth;
            centerW -= totalWidth;
            west.applyLayout(b);
        }
        if (e && e.isVisible()) {
            b = e.getSize();
            m = e.getMargins();
            b.height = centerH - (m.top + m.bottom);
            totalWidth = (b.width + m.left + m.right);
            b.x = w - totalWidth + m.left;
            b.y = centerY + m.top;
            centerW -= totalWidth;
            e.applyLayout(b);
        }
        if (c) {
            m = c.getMargins();
            var centerBox = {
                x: centerX + m.left,
                y: centerY + m.top,
                width: centerW - (m.left + m.right),
                height: centerH - (m.top + m.bottom)
            };
            c.applyLayout(centerBox);
        }
        if (collapsed) {
            for (i = 0, len = collapsed.length; i < len; i++) {
                collapsed[i].collapse(false);
            }
        }
        if (Ext.isIE && Ext.isStrict) {
            target.repaint();
        }

        if (i = target.getStyle('overflow') && i != 'hidden' && !this.adjustmentPass) {
            var ts = this.getLayoutTargetSize();
            if (ts.width != size.width || ts.height != size.height) {
                this.adjustmentPass = true;
                this.onLayout(ct, target);
            }
        }
        delete this.adjustmentPass;
    },

    destroy: function () {
        var r = ['north', 'south', 'east', 'west'], i, region;
        for (i = 0; i < r.length; i++) {
            region = this[r[i]];
            if (region) {
                if (region.destroy) {
                    region.destroy();
                } else if (region.split) {
                    region.split.destroy(true);
                }
            }
        }
        Ext.layout.BorderLayout.superclass.destroy.call(this);
    }


});


Ext.layout.BorderLayout.Region = function (layout, config, pos) {
    Ext.apply(this, config);
    this.layout = layout;
    this.position = pos;
    this.state = {};
    if (typeof this.margins == 'string') {
        this.margins = this.layout.parseMargins(this.margins);
    }
    this.margins = Ext.applyIf(this.margins || {}, this.defaultMargins);
    if (this.collapsible) {
        if (typeof this.cmargins == 'string') {
            this.cmargins = this.layout.parseMargins(this.cmargins);
        }
        if (this.collapseMode == 'mini' && !this.cmargins) {
            this.cmargins = { left: 0, top: 0, right: 0, bottom: 0 };
        } else {
            this.cmargins = Ext.applyIf(this.cmargins || {},
                pos == 'north' || pos == 'south' ? this.defaultNSCMargins : this.defaultEWCMargins);
        }
    }
};

Ext.layout.BorderLayout.Region.prototype = {






    collapsible: false,

    split: false,

    floatable: true,

    minWidth: 50,

    minHeight: 50,


    defaultMargins: { left: 0, top: 0, right: 0, bottom: 0 },

    defaultNSCMargins: { left: 5, top: 5, right: 5, bottom: 5 },

    defaultEWCMargins: { left: 5, top: 0, right: 5, bottom: 0 },
    floatingZIndex: 100,


    isCollapsed: false,






    render: function (ct, p) {
        this.panel = p;
        p.el.enableDisplayMode();
        this.targetEl = ct;
        this.el = p.el;

        var gs = p.getState, ps = this.position;
        p.getState = function () {
            return Ext.apply(gs.call(p) || {}, this.state);
        } .createDelegate(this);

        if (ps != 'center') {
            p.allowQueuedExpand = false;
            p.on({
                beforecollapse: this.beforeCollapse,
                collapse: this.onCollapse,
                beforeexpand: this.beforeExpand,
                expand: this.onExpand,
                hide: this.onHide,
                show: this.onShow,
                scope: this
            });
            if (this.collapsible || this.floatable) {
                p.collapseEl = 'el';
                p.slideAnchor = this.getSlideAnchor();
            }
            if (p.tools && p.tools.toggle) {
                p.tools.toggle.addClass('x-tool-collapse-' + ps);
                p.tools.toggle.addClassOnOver('x-tool-collapse-' + ps + '-over');
            }
        }
    },


    getCollapsedEl: function () {
        if (!this.collapsedEl) {
            if (!this.toolTemplate) {
                var tt = new Ext.Template(
                     '<div class="x-tool x-tool-{id}">&#160;</div>'
                );
                tt.disableFormats = true;
                tt.compile();
                Ext.layout.BorderLayout.Region.prototype.toolTemplate = tt;
            }
            this.collapsedEl = this.targetEl.createChild({
                cls: "x-layout-collapsed x-layout-collapsed-" + this.position,
                id: this.panel.id + '-xcollapsed'
            });
            this.collapsedEl.enableDisplayMode('block');

            if (this.collapseMode == 'mini') {
                this.collapsedEl.addClass('x-layout-cmini-' + this.position);
                this.miniCollapsedEl = this.collapsedEl.createChild({
                    cls: "x-layout-mini x-layout-mini-" + this.position, html: "&#160;"
                });
                this.miniCollapsedEl.addClassOnOver('x-layout-mini-over');
                this.collapsedEl.addClassOnOver("x-layout-collapsed-over");
                this.collapsedEl.on('click', this.onExpandClick, this, { stopEvent: true });
            } else {
                if (this.collapsible !== false && !this.hideCollapseTool) {
                    var t = this.expandToolEl = this.toolTemplate.append(
                            this.collapsedEl.dom,
                            { id: 'expand-' + this.position }, true);
                    t.addClassOnOver('x-tool-expand-' + this.position + '-over');
                    t.on('click', this.onExpandClick, this, { stopEvent: true });
                }
                if (this.floatable !== false || this.titleCollapse) {
                    this.collapsedEl.addClassOnOver("x-layout-collapsed-over");
                    this.collapsedEl.on("click", this[this.floatable ? 'collapseClick' : 'onExpandClick'], this);
                }
            }
        }
        return this.collapsedEl;
    },


    onExpandClick: function (e) {
        if (this.isSlid) {
            this.panel.expand(false);
        } else {
            this.panel.expand();
        }
    },


    onCollapseClick: function (e) {
        this.panel.collapse();
    },


    beforeCollapse: function (p, animate) {
        this.lastAnim = animate;
        if (this.splitEl) {
            this.splitEl.hide();
        }
        this.getCollapsedEl().show();
        var el = this.panel.getEl();
        this.originalZIndex = el.getStyle('z-index');
        el.setStyle('z-index', 100);
        this.isCollapsed = true;
        this.layout.layout();
    },


    onCollapse: function (animate) {
        this.panel.el.setStyle('z-index', 1);
        if (this.lastAnim === false || this.panel.animCollapse === false) {
            this.getCollapsedEl().dom.style.visibility = 'visible';
        } else {
            this.getCollapsedEl().slideIn(this.panel.slideAnchor, { duration: .2 });
        }
        this.state.collapsed = true;
        this.panel.saveState();
    },


    beforeExpand: function (animate) {
        if (this.isSlid) {
            this.afterSlideIn();
        }
        var c = this.getCollapsedEl();
        this.el.show();
        if (this.position == 'east' || this.position == 'west') {
            this.panel.setSize(undefined, c.getHeight());
        } else {
            this.panel.setSize(c.getWidth(), undefined);
        }
        c.hide();
        c.dom.style.visibility = 'hidden';
        this.panel.el.setStyle('z-index', this.floatingZIndex);
    },


    onExpand: function () {
        this.isCollapsed = false;
        if (this.splitEl) {
            this.splitEl.show();
        }
        this.layout.layout();
        this.panel.el.setStyle('z-index', this.originalZIndex);
        this.state.collapsed = false;
        this.panel.saveState();
    },


    collapseClick: function (e) {
        if (this.isSlid) {
            e.stopPropagation();
            this.slideIn();
        } else {
            e.stopPropagation();
            this.slideOut();
        }
    },


    onHide: function () {
        if (this.isCollapsed) {
            this.getCollapsedEl().hide();
        } else if (this.splitEl) {
            this.splitEl.hide();
        }
    },


    onShow: function () {
        if (this.isCollapsed) {
            this.getCollapsedEl().show();
        } else if (this.splitEl) {
            this.splitEl.show();
        }
    },


    isVisible: function () {
        return !this.panel.hidden;
    },


    getMargins: function () {
        return this.isCollapsed && this.cmargins ? this.cmargins : this.margins;
    },


    getSize: function () {
        return this.isCollapsed ? this.getCollapsedEl().getSize() : this.panel.getSize();
    },


    setPanel: function (panel) {
        this.panel = panel;
    },


    getMinWidth: function () {
        return this.minWidth;
    },


    getMinHeight: function () {
        return this.minHeight;
    },


    applyLayoutCollapsed: function (box) {
        var ce = this.getCollapsedEl();
        ce.setLeftTop(box.x, box.y);
        ce.setSize(box.width, box.height);
    },


    applyLayout: function (box) {
        if (this.isCollapsed) {
            this.applyLayoutCollapsed(box);
        } else {
            this.panel.setPosition(box.x, box.y);
            this.panel.setSize(box.width, box.height);
        }
    },


    beforeSlide: function () {
        this.panel.beforeEffect();
    },


    afterSlide: function () {
        this.panel.afterEffect();
    },


    initAutoHide: function () {
        if (this.autoHide !== false) {
            if (!this.autoHideHd) {
                this.autoHideSlideTask = new Ext.util.DelayedTask(this.slideIn, this);
                this.autoHideHd = {
                    "mouseout": function (e) {
                        if (!e.within(this.el, true)) {
                            this.autoHideSlideTask.delay(500);
                        }
                    },
                    "mouseover": function (e) {
                        this.autoHideSlideTask.cancel();
                    },
                    scope: this
                };
            }
            this.el.on(this.autoHideHd);
            this.collapsedEl.on(this.autoHideHd);
        }
    },


    clearAutoHide: function () {
        if (this.autoHide !== false) {
            this.el.un("mouseout", this.autoHideHd.mouseout);
            this.el.un("mouseover", this.autoHideHd.mouseover);
            this.collapsedEl.un("mouseout", this.autoHideHd.mouseout);
            this.collapsedEl.un("mouseover", this.autoHideHd.mouseover);
        }
    },


    clearMonitor: function () {
        Ext.getDoc().un("click", this.slideInIf, this);
    },


    slideOut: function () {
        if (this.isSlid || this.el.hasActiveFx()) {
            return;
        }
        this.isSlid = true;
        var ts = this.panel.tools, dh, pc;
        if (ts && ts.toggle) {
            ts.toggle.hide();
        }
        this.el.show();


        pc = this.panel.collapsed;
        this.panel.collapsed = false;

        if (this.position == 'east' || this.position == 'west') {

            dh = this.panel.deferHeight;
            this.panel.deferHeight = false;

            this.panel.setSize(undefined, this.collapsedEl.getHeight());


            this.panel.deferHeight = dh;
        } else {
            this.panel.setSize(this.collapsedEl.getWidth(), undefined);
        }


        this.panel.collapsed = pc;

        this.restoreLT = [this.el.dom.style.left, this.el.dom.style.top];
        this.el.alignTo(this.collapsedEl, this.getCollapseAnchor());
        this.el.setStyle("z-index", this.floatingZIndex + 2);
        this.panel.el.replaceClass('x-panel-collapsed', 'x-panel-floating');
        if (this.animFloat !== false) {
            this.beforeSlide();
            this.el.slideIn(this.getSlideAnchor(), {
                callback: function () {
                    this.afterSlide();
                    this.initAutoHide();
                    Ext.getDoc().on("click", this.slideInIf, this);
                },
                scope: this,
                block: true
            });
        } else {
            this.initAutoHide();
            Ext.getDoc().on("click", this.slideInIf, this);
        }
    },


    afterSlideIn: function () {
        this.clearAutoHide();
        this.isSlid = false;
        this.clearMonitor();
        this.el.setStyle("z-index", "");
        this.panel.el.replaceClass('x-panel-floating', 'x-panel-collapsed');
        this.el.dom.style.left = this.restoreLT[0];
        this.el.dom.style.top = this.restoreLT[1];

        var ts = this.panel.tools;
        if (ts && ts.toggle) {
            ts.toggle.show();
        }
    },


    slideIn: function (cb) {
        if (!this.isSlid || this.el.hasActiveFx()) {
            Ext.callback(cb);
            return;
        }
        this.isSlid = false;
        if (this.animFloat !== false) {
            this.beforeSlide();
            this.el.slideOut(this.getSlideAnchor(), {
                callback: function () {
                    this.el.hide();
                    this.afterSlide();
                    this.afterSlideIn();
                    Ext.callback(cb);
                },
                scope: this,
                block: true
            });
        } else {
            this.el.hide();
            this.afterSlideIn();
        }
    },


    slideInIf: function (e) {
        if (!e.within(this.el)) {
            this.slideIn();
        }
    },


    anchors: {
        "west": "left",
        "east": "right",
        "north": "top",
        "south": "bottom"
    },


    sanchors: {
        "west": "l",
        "east": "r",
        "north": "t",
        "south": "b"
    },


    canchors: {
        "west": "tl-tr",
        "east": "tr-tl",
        "north": "tl-bl",
        "south": "bl-tl"
    },


    getAnchor: function () {
        return this.anchors[this.position];
    },


    getCollapseAnchor: function () {
        return this.canchors[this.position];
    },


    getSlideAnchor: function () {
        return this.sanchors[this.position];
    },


    getAlignAdj: function () {
        var cm = this.cmargins;
        switch (this.position) {
            case "west":
                return [0, 0];
                break;
            case "east":
                return [0, 0];
                break;
            case "north":
                return [0, 0];
                break;
            case "south":
                return [0, 0];
                break;
        }
    },


    getExpandAdj: function () {
        var c = this.collapsedEl, cm = this.cmargins;
        switch (this.position) {
            case "west":
                return [-(cm.right + c.getWidth() + cm.left), 0];
                break;
            case "east":
                return [cm.right + c.getWidth() + cm.left, 0];
                break;
            case "north":
                return [0, -(cm.top + cm.bottom + c.getHeight())];
                break;
            case "south":
                return [0, cm.top + cm.bottom + c.getHeight()];
                break;
        }
    },

    destroy: function () {
        if (this.autoHideSlideTask && this.autoHideSlideTask.cancel) {
            this.autoHideSlideTask.cancel();
        }
        Ext.destroyMembers(this, 'miniCollapsedEl', 'collapsedEl', 'expandToolEl');
    }
};


Ext.layout.BorderLayout.SplitRegion = function (layout, config, pos) {
    Ext.layout.BorderLayout.SplitRegion.superclass.constructor.call(this, layout, config, pos);

    this.applyLayout = this.applyFns[pos];
};

Ext.extend(Ext.layout.BorderLayout.SplitRegion, Ext.layout.BorderLayout.Region, {


    splitTip: "Drag to resize.",

    collapsibleSplitTip: "Drag to resize. Double click to hide.",

    useSplitTips: false,


    splitSettings: {
        north: {
            orientation: Ext.SplitBar.VERTICAL,
            placement: Ext.SplitBar.TOP,
            maxFn: 'getVMaxSize',
            minProp: 'minHeight',
            maxProp: 'maxHeight'
        },
        south: {
            orientation: Ext.SplitBar.VERTICAL,
            placement: Ext.SplitBar.BOTTOM,
            maxFn: 'getVMaxSize',
            minProp: 'minHeight',
            maxProp: 'maxHeight'
        },
        east: {
            orientation: Ext.SplitBar.HORIZONTAL,
            placement: Ext.SplitBar.RIGHT,
            maxFn: 'getHMaxSize',
            minProp: 'minWidth',
            maxProp: 'maxWidth'
        },
        west: {
            orientation: Ext.SplitBar.HORIZONTAL,
            placement: Ext.SplitBar.LEFT,
            maxFn: 'getHMaxSize',
            minProp: 'minWidth',
            maxProp: 'maxWidth'
        }
    },


    applyFns: {
        west: function (box) {
            if (this.isCollapsed) {
                return this.applyLayoutCollapsed(box);
            }
            var sd = this.splitEl.dom, s = sd.style;
            this.panel.setPosition(box.x, box.y);
            var sw = sd.offsetWidth;
            s.left = (box.x + box.width - sw) + 'px';
            s.top = (box.y) + 'px';
            s.height = Math.max(0, box.height) + 'px';
            this.panel.setSize(box.width - sw, box.height);
        },
        east: function (box) {
            if (this.isCollapsed) {
                return this.applyLayoutCollapsed(box);
            }
            var sd = this.splitEl.dom, s = sd.style;
            var sw = sd.offsetWidth;
            this.panel.setPosition(box.x + sw, box.y);
            s.left = (box.x) + 'px';
            s.top = (box.y) + 'px';
            s.height = Math.max(0, box.height) + 'px';
            this.panel.setSize(box.width - sw, box.height);
        },
        north: function (box) {
            if (this.isCollapsed) {
                return this.applyLayoutCollapsed(box);
            }
            var sd = this.splitEl.dom, s = sd.style;
            var sh = sd.offsetHeight;
            this.panel.setPosition(box.x, box.y);
            s.left = (box.x) + 'px';
            s.top = (box.y + box.height - sh) + 'px';
            s.width = Math.max(0, box.width) + 'px';
            this.panel.setSize(box.width, box.height - sh);
        },
        south: function (box) {
            if (this.isCollapsed) {
                return this.applyLayoutCollapsed(box);
            }
            var sd = this.splitEl.dom, s = sd.style;
            var sh = sd.offsetHeight;
            this.panel.setPosition(box.x, box.y + sh);
            s.left = (box.x) + 'px';
            s.top = (box.y) + 'px';
            s.width = Math.max(0, box.width) + 'px';
            this.panel.setSize(box.width, box.height - sh);
        }
    },


    render: function (ct, p) {
        Ext.layout.BorderLayout.SplitRegion.superclass.render.call(this, ct, p);

        var ps = this.position;

        this.splitEl = ct.createChild({
            cls: "x-layout-split x-layout-split-" + ps, html: "&#160;",
            id: this.panel.id + '-xsplit'
        });

        if (this.collapseMode == 'mini') {
            this.miniSplitEl = this.splitEl.createChild({
                cls: "x-layout-mini x-layout-mini-" + ps, html: "&#160;"
            });
            this.miniSplitEl.addClassOnOver('x-layout-mini-over');
            this.miniSplitEl.on('click', this.onCollapseClick, this, { stopEvent: true });
        }

        var s = this.splitSettings[ps];

        this.split = new Ext.SplitBar(this.splitEl.dom, p.el, s.orientation);
        this.split.tickSize = this.tickSize;
        this.split.placement = s.placement;
        this.split.getMaximumSize = this[s.maxFn].createDelegate(this);
        this.split.minSize = this.minSize || this[s.minProp];
        this.split.on("beforeapply", this.onSplitMove, this);
        this.split.useShim = this.useShim === true;
        this.maxSize = this.maxSize || this[s.maxProp];

        if (p.hidden) {
            this.splitEl.hide();
        }

        if (this.useSplitTips) {
            this.splitEl.dom.title = this.collapsible ? this.collapsibleSplitTip : this.splitTip;
        }
        if (this.collapsible) {
            this.splitEl.on("dblclick", this.onCollapseClick, this);
        }
    },


    getSize: function () {
        if (this.isCollapsed) {
            return this.collapsedEl.getSize();
        }
        var s = this.panel.getSize();
        if (this.position == 'north' || this.position == 'south') {
            s.height += this.splitEl.dom.offsetHeight;
        } else {
            s.width += this.splitEl.dom.offsetWidth;
        }
        return s;
    },


    getHMaxSize: function () {
        var cmax = this.maxSize || 10000;
        var center = this.layout.center;
        return Math.min(cmax, (this.el.getWidth() + center.el.getWidth()) - center.getMinWidth());
    },


    getVMaxSize: function () {
        var cmax = this.maxSize || 10000;
        var center = this.layout.center;
        return Math.min(cmax, (this.el.getHeight() + center.el.getHeight()) - center.getMinHeight());
    },


    onSplitMove: function (split, newSize) {
        var s = this.panel.getSize();
        this.lastSplitSize = newSize;
        if (this.position == 'north' || this.position == 'south') {
            this.panel.setSize(s.width, newSize);
            this.state.height = newSize;
        } else {
            this.panel.setSize(newSize, s.height);
            this.state.width = newSize;
        }
        this.layout.layout();
        this.panel.saveState();
        return false;
    },


    getSplitBar: function () {
        return this.split;
    },


    destroy: function () {
        Ext.destroy(this.miniSplitEl, this.split, this.splitEl);
        Ext.layout.BorderLayout.SplitRegion.superclass.destroy.call(this);
    }
});

Ext.Container.LAYOUTS['border'] = Ext.layout.BorderLayout;

Ext.layout.FormLayout = Ext.extend(Ext.layout.AnchorLayout, {


    labelSeparator: ':',




    trackLabels: true,

    type: 'form',

    onRemove: function (c) {
        Ext.layout.FormLayout.superclass.onRemove.call(this, c);
        if (this.trackLabels) {
            c.un('show', this.onFieldShow, this);
            c.un('hide', this.onFieldHide, this);
        }

        var el = c.getPositionEl(),
            ct = c.getItemCt && c.getItemCt();
        if (c.rendered && ct) {
            if (el && el.dom) {
                el.insertAfter(ct);
            }
            Ext.destroy(ct);
            Ext.destroyMembers(c, 'label', 'itemCt');
            if (c.customItemCt) {
                Ext.destroyMembers(c, 'getItemCt', 'customItemCt');
            }
        }
    },


    setContainer: function (ct) {
        Ext.layout.FormLayout.superclass.setContainer.call(this, ct);
        if (ct.labelAlign) {
            ct.addClass('x-form-label-' + ct.labelAlign);
        }

        if (ct.hideLabels) {
            Ext.apply(this, {
                labelStyle: 'display:none',
                elementStyle: 'padding-left:0;',
                labelAdjust: 0
            });
        } else {
            this.labelSeparator = Ext.isDefined(ct.labelSeparator) ? ct.labelSeparator : this.labelSeparator;
            ct.labelWidth = ct.labelWidth || 100;
            if (Ext.isNumber(ct.labelWidth)) {
                var pad = Ext.isNumber(ct.labelPad) ? ct.labelPad : 5;
                Ext.apply(this, {
                    labelAdjust: ct.labelWidth + pad,
                    labelStyle: 'width:' + ct.labelWidth + 'px;',
                    elementStyle: 'padding-left:' + (ct.labelWidth + pad) + 'px'
                });
            }
            if (ct.labelAlign == 'top') {
                Ext.apply(this, {
                    labelStyle: 'width:auto;',
                    labelAdjust: 0,
                    elementStyle: 'padding-left:0;'
                });
            }
        }
    },


    isHide: function (c) {
        return c.hideLabel || this.container.hideLabels;
    },

    onFieldShow: function (c) {
        c.getItemCt().removeClass('x-hide-' + c.hideMode);


        if (c.isComposite) {
            c.doLayout();
        }
    },

    onFieldHide: function (c) {
        c.getItemCt().addClass('x-hide-' + c.hideMode);
    },


    getLabelStyle: function (s) {
        var ls = '', items = [this.labelStyle, s];
        for (var i = 0, len = items.length; i < len; ++i) {
            if (items[i]) {
                ls += items[i];
                if (ls.substr(-1, 1) != ';') {
                    ls += ';';
                }
            }
        }
        return ls;
    },




    renderItem: function (c, position, target) {
        if (c && (c.isFormField || c.fieldLabel) && c.inputType != 'hidden') {
            var args = this.getTemplateArgs(c);
            if (Ext.isNumber(position)) {
                position = target.dom.childNodes[position] || null;
            }
            if (position) {
                c.itemCt = this.fieldTpl.insertBefore(position, args, true);
            } else {
                c.itemCt = this.fieldTpl.append(target, args, true);
            }
            if (!c.getItemCt) {


                Ext.apply(c, {
                    getItemCt: function () {
                        return c.itemCt;
                    },
                    customItemCt: true
                });
            }
            c.label = c.getItemCt().child('label.x-form-item-label');
            if (!c.rendered) {
                c.render('x-form-el-' + c.id);
            } else if (!this.isValidParent(c, target)) {
                Ext.fly('x-form-el-' + c.id).appendChild(c.getPositionEl());
            }
            if (this.trackLabels) {
                if (c.hidden) {
                    this.onFieldHide(c);
                }
                c.on({
                    scope: this,
                    show: this.onFieldShow,
                    hide: this.onFieldHide
                });
            }
            this.configureItem(c);
        } else {
            Ext.layout.FormLayout.superclass.renderItem.apply(this, arguments);
        }
    },


    getTemplateArgs: function (field) {
        var noLabelSep = !field.fieldLabel || field.hideLabel;

        return {
            id: field.id,
            label: field.fieldLabel,
            itemCls: (field.itemCls || this.container.itemCls || '') + (field.hideLabel ? ' x-hide-label' : ''),
            clearCls: field.clearCls || 'x-form-clear-left',
            labelStyle: this.getLabelStyle(field.labelStyle),
            elementStyle: this.elementStyle || '',
            labelSeparator: noLabelSep ? '' : (Ext.isDefined(field.labelSeparator) ? field.labelSeparator : this.labelSeparator)
        };
    },


    adjustWidthAnchor: function (value, c) {
        if (c.label && !this.isHide(c) && (this.container.labelAlign != 'top')) {
            var adjust = Ext.isIE6 || (Ext.isIE && !Ext.isStrict);
            return value - this.labelAdjust + (adjust ? -3 : 0);
        }
        return value;
    },

    adjustHeightAnchor: function (value, c) {
        if (c.label && !this.isHide(c) && (this.container.labelAlign == 'top')) {
            return value - c.label.getHeight();
        }
        return value;
    },


    isValidParent: function (c, target) {
        return target && this.container.getEl().contains(c.getPositionEl());
    }


});

Ext.Container.LAYOUTS['form'] = Ext.layout.FormLayout;

Ext.layout.AccordionLayout = Ext.extend(Ext.layout.FitLayout, {

    fill: true,

    autoWidth: true,

    titleCollapse: true,

    hideCollapseTool: false,

    collapseFirst: false,

    animate: false,

    sequence: false,

    activeOnTop: false,

    type: 'accordion',

    renderItem: function (c) {
        if (this.animate === false) {
            c.animCollapse = false;
        }
        c.collapsible = true;
        if (this.autoWidth) {
            c.autoWidth = true;
        }
        if (this.titleCollapse) {
            c.titleCollapse = true;
        }
        if (this.hideCollapseTool) {
            c.hideCollapseTool = true;
        }
        if (this.collapseFirst !== undefined) {
            c.collapseFirst = this.collapseFirst;
        }
        if (!this.activeItem && !c.collapsed) {
            this.setActiveItem(c, true);
        } else if (this.activeItem && this.activeItem != c) {
            c.collapsed = true;
        }
        Ext.layout.AccordionLayout.superclass.renderItem.apply(this, arguments);
        c.header.addClass('x-accordion-hd');
        c.on('beforeexpand', this.beforeExpand, this);
    },

    onRemove: function (c) {
        Ext.layout.AccordionLayout.superclass.onRemove.call(this, c);
        if (c.rendered) {
            c.header.removeClass('x-accordion-hd');
        }
        c.un('beforeexpand', this.beforeExpand, this);
    },


    beforeExpand: function (p, anim) {
        var ai = this.activeItem;
        if (ai) {
            if (this.sequence) {
                delete this.activeItem;
                if (!ai.collapsed) {
                    ai.collapse({ callback: function () {
                        p.expand(anim || true);
                    }, scope: this
                    });
                    return false;
                }
            } else {
                ai.collapse(this.animate);
            }
        }
        this.setActive(p);
        if (this.activeOnTop) {
            p.el.dom.parentNode.insertBefore(p.el.dom, p.el.dom.parentNode.firstChild);
        }

        this.layout();
    },


    setItemSize: function (item, size) {
        if (this.fill && item) {
            var hh = 0, i, ct = this.getRenderedItems(this.container), len = ct.length, p;

            for (i = 0; i < len; i++) {
                if ((p = ct[i]) != item && !p.hidden) {
                    hh += p.header.getHeight();
                }
            };

            size.height -= hh;


            item.setSize(size);
        }
    },


    setActiveItem: function (item) {
        this.setActive(item, true);
    },


    setActive: function (item, expand) {
        var ai = this.activeItem;
        item = this.container.getComponent(item);
        if (ai != item) {
            if (item.rendered && item.collapsed && expand) {
                item.expand();
            } else {
                if (ai) {
                    ai.fireEvent('deactivate', ai);
                }
                this.activeItem = item;
                item.fireEvent('activate', item);
            }
        }
    }
});
Ext.Container.LAYOUTS.accordion = Ext.layout.AccordionLayout;


Ext.layout.Accordion = Ext.layout.AccordionLayout;
Ext.layout.TableLayout = Ext.extend(Ext.layout.ContainerLayout, {



    monitorResize: false,

    type: 'table',

    targetCls: 'x-table-layout-ct',


    tableAttrs: null,


    setContainer: function (ct) {
        Ext.layout.TableLayout.superclass.setContainer.call(this, ct);

        this.currentRow = 0;
        this.currentColumn = 0;
        this.cells = [];
    },


    onLayout: function (ct, target) {
        var cs = ct.items.items, len = cs.length, c, i;

        if (!this.table) {
            target.addClass('x-table-layout-ct');

            this.table = target.createChild(
                Ext.apply({ tag: 'table', cls: 'x-table-layout', cellspacing: 0, cn: { tag: 'tbody'} }, this.tableAttrs), null, true);
        }
        this.renderAll(ct, target);
    },


    getRow: function (index) {
        var row = this.table.tBodies[0].childNodes[index];
        if (!row) {
            row = document.createElement('tr');
            this.table.tBodies[0].appendChild(row);
        }
        return row;
    },


    getNextCell: function (c) {
        var cell = this.getNextNonSpan(this.currentColumn, this.currentRow);
        var curCol = this.currentColumn = cell[0], curRow = this.currentRow = cell[1];
        for (var rowIndex = curRow; rowIndex < curRow + (c.rowspan || 1); rowIndex++) {
            if (!this.cells[rowIndex]) {
                this.cells[rowIndex] = [];
            }
            for (var colIndex = curCol; colIndex < curCol + (c.colspan || 1); colIndex++) {
                this.cells[rowIndex][colIndex] = true;
            }
        }
        var td = document.createElement('td');
        if (c.cellId) {
            td.id = c.cellId;
        }
        var cls = 'x-table-layout-cell';
        if (c.cellCls) {
            cls += ' ' + c.cellCls;
        }
        td.className = cls;
        if (c.colspan) {
            td.colSpan = c.colspan;
        }
        if (c.rowspan) {
            td.rowSpan = c.rowspan;
        }
        this.getRow(curRow).appendChild(td);
        return td;
    },


    getNextNonSpan: function (colIndex, rowIndex) {
        var cols = this.columns;
        while ((cols && colIndex >= cols) || (this.cells[rowIndex] && this.cells[rowIndex][colIndex])) {
            if (cols && colIndex >= cols) {
                rowIndex++;
                colIndex = 0;
            } else {
                colIndex++;
            }
        }
        return [colIndex, rowIndex];
    },


    renderItem: function (c, position, target) {

        if (!this.table) {
            this.table = target.createChild(
                Ext.apply({ tag: 'table', cls: 'x-table-layout', cellspacing: 0, cn: { tag: 'tbody'} }, this.tableAttrs), null, true);
        }
        if (c && !c.rendered) {
            c.render(this.getNextCell(c));
            this.configureItem(c);
        } else if (c && !this.isValidParent(c, target)) {
            var container = this.getNextCell(c);
            container.insertBefore(c.getPositionEl().dom, null);
            c.container = Ext.get(container);
            this.configureItem(c);
        }
    },


    isValidParent: function (c, target) {
        return c.getPositionEl().up('table', 5).dom.parentNode === (target.dom || target);
    },

    destroy: function () {
        delete this.table;
        Ext.layout.TableLayout.superclass.destroy.call(this);
    }


});

Ext.Container.LAYOUTS['table'] = Ext.layout.TableLayout;
Ext.layout.AbsoluteLayout = Ext.extend(Ext.layout.AnchorLayout, {

    extraCls: 'x-abs-layout-item',

    type: 'absolute',

    onLayout: function (ct, target) {
        target.position();
        this.paddingLeft = target.getPadding('l');
        this.paddingTop = target.getPadding('t');
        Ext.layout.AbsoluteLayout.superclass.onLayout.call(this, ct, target);
    },


    adjustWidthAnchor: function (value, comp) {
        return value ? value - comp.getPosition(true)[0] + this.paddingLeft : value;
    },


    adjustHeightAnchor: function (value, comp) {
        return value ? value - comp.getPosition(true)[1] + this.paddingTop : value;
    }

});
Ext.Container.LAYOUTS['absolute'] = Ext.layout.AbsoluteLayout;

Ext.layout.BoxLayout = Ext.extend(Ext.layout.ContainerLayout, {

    defaultMargins: { left: 0, top: 0, right: 0, bottom: 0 },

    padding: '0',

    pack: 'start',


    monitorResize: true,
    type: 'box',
    scrollOffset: 0,
    extraCls: 'x-box-item',
    targetCls: 'x-box-layout-ct',
    innerCls: 'x-box-inner',

    constructor: function (config) {
        Ext.layout.BoxLayout.superclass.constructor.call(this, config);

        if (Ext.isString(this.defaultMargins)) {
            this.defaultMargins = this.parseMargins(this.defaultMargins);
        }

        var handler = this.overflowHandler;

        if (typeof handler == 'string') {
            handler = {
                type: handler
            };
        }

        var handlerType = 'none';
        if (handler && handler.type != undefined) {
            handlerType = handler.type;
        }

        var constructor = Ext.layout.boxOverflow[handlerType];
        if (constructor[this.type]) {
            constructor = constructor[this.type];
        }

        this.overflowHandler = new constructor(this, handler);
    },


    onLayout: function (container, target) {
        Ext.layout.BoxLayout.superclass.onLayout.call(this, container, target);

        var tSize = this.getLayoutTargetSize(),
            items = this.getVisibleItems(container),
            calcs = this.calculateChildBoxes(items, tSize),
            boxes = calcs.boxes,
            meta = calcs.meta;


        if (tSize.width > 0) {
            var handler = this.overflowHandler,
                method = meta.tooNarrow ? 'handleOverflow' : 'clearOverflow';

            var results = handler[method](calcs, tSize);

            if (results) {
                if (results.targetSize) {
                    tSize = results.targetSize;
                }

                if (results.recalculate) {
                    items = this.getVisibleItems(container);
                    calcs = this.calculateChildBoxes(items, tSize);
                    boxes = calcs.boxes;
                }
            }
        }


        this.layoutTargetLastSize = tSize;


        this.childBoxCache = calcs;

        this.updateInnerCtSize(tSize, calcs);
        this.updateChildBoxes(boxes);


        this.handleTargetOverflow(tSize, container, target);
    },


    updateChildBoxes: function (boxes) {
        for (var i = 0, length = boxes.length; i < length; i++) {
            var box = boxes[i],
                comp = box.component;

            if (box.dirtySize) {
                comp.setSize(box.width, box.height);
            }

            if (isNaN(box.left) || isNaN(box.top)) {
                continue;
            }

            comp.setPosition(box.left, box.top);
        }
    },


    updateInnerCtSize: function (tSize, calcs) {
        var align = this.align,
            padding = this.padding,
            width = tSize.width,
            height = tSize.height;

        if (this.type == 'hbox') {
            var innerCtWidth = width,
                innerCtHeight = calcs.meta.maxHeight + padding.top + padding.bottom;

            if (align == 'stretch') {
                innerCtHeight = height;
            } else if (align == 'middle') {
                innerCtHeight = Math.max(height, innerCtHeight);
            }
        } else {
            var innerCtHeight = height,
                innerCtWidth = calcs.meta.maxWidth + padding.left + padding.right;

            if (align == 'stretch') {
                innerCtWidth = width;
            } else if (align == 'center') {
                innerCtWidth = Math.max(width, innerCtWidth);
            }
        }

        this.innerCt.setSize(innerCtWidth || undefined, innerCtHeight || undefined);
    },


    handleTargetOverflow: function (previousTargetSize, container, target) {
        var overflow = target.getStyle('overflow');

        if (overflow && overflow != 'hidden' && !this.adjustmentPass) {
            var newTargetSize = this.getLayoutTargetSize();
            if (newTargetSize.width != previousTargetSize.width || newTargetSize.height != previousTargetSize.height) {
                this.adjustmentPass = true;
                this.onLayout(container, target);
            }
        }

        delete this.adjustmentPass;
    },


    isValidParent: function (c, target) {
        return this.innerCt && c.getPositionEl().dom.parentNode == this.innerCt.dom;
    },


    getVisibleItems: function (ct) {
        var ct = ct || this.container,
            t = ct.getLayoutTarget(),
            cti = ct.items.items,
            len = cti.length,

            i, c, items = [];

        for (i = 0; i < len; i++) {
            if ((c = cti[i]).rendered && this.isValidParent(c, t) && c.hidden !== true && c.collapsed !== true && c.shouldLayout !== false) {
                items.push(c);
            }
        }

        return items;
    },


    renderAll: function (ct, target) {
        if (!this.innerCt) {

            this.innerCt = target.createChild({ cls: this.innerCls });
            this.padding = this.parseMargins(this.padding);
        }
        Ext.layout.BoxLayout.superclass.renderAll.call(this, ct, this.innerCt);
    },

    getLayoutTargetSize: function () {
        var target = this.container.getLayoutTarget(), ret;

        if (target) {
            ret = target.getViewSize();




            if (Ext.isIE && Ext.isStrict && ret.width == 0) {
                ret = target.getStyleSize();
            }

            ret.width -= target.getPadding('lr');
            ret.height -= target.getPadding('tb');
        }

        return ret;
    },


    renderItem: function (c) {
        if (Ext.isString(c.margins)) {
            c.margins = this.parseMargins(c.margins);
        } else if (!c.margins) {
            c.margins = this.defaultMargins;
        }
        Ext.layout.BoxLayout.superclass.renderItem.apply(this, arguments);
    },


    destroy: function () {
        Ext.destroy(this.overflowHandler);

        Ext.layout.BoxLayout.superclass.destroy.apply(this, arguments);
    }
});



Ext.ns('Ext.layout.boxOverflow');



Ext.layout.boxOverflow.None = Ext.extend(Object, {
    constructor: function (layout, config) {
        this.layout = layout;

        Ext.apply(this, config || {});
    },

    handleOverflow: Ext.emptyFn,

    clearOverflow: Ext.emptyFn
});


Ext.layout.boxOverflow.none = Ext.layout.boxOverflow.None;

Ext.layout.boxOverflow.Menu = Ext.extend(Ext.layout.boxOverflow.None, {

    afterCls: 'x-strip-right',


    noItemsMenuText: '<div class="x-toolbar-no-items">(None)</div>',

    constructor: function (layout) {
        Ext.layout.boxOverflow.Menu.superclass.constructor.apply(this, arguments);


        this.menuItems = [];
    },


    createInnerElements: function () {
        if (!this.afterCt) {
            this.afterCt = this.layout.innerCt.insertSibling({ cls: this.afterCls }, 'before');
        }
    },


    clearOverflow: function (calculations, targetSize) {
        var newWidth = targetSize.width + (this.afterCt ? this.afterCt.getWidth() : 0),
            items = this.menuItems;

        this.hideTrigger();

        for (var index = 0, length = items.length; index < length; index++) {
            items.pop().component.show();
        }

        return {
            targetSize: {
                height: targetSize.height,
                width: newWidth
            }
        };
    },


    showTrigger: function () {
        this.createMenu();
        this.menuTrigger.show();
    },


    hideTrigger: function () {
        if (this.menuTrigger != undefined) {
            this.menuTrigger.hide();
        }
    },


    beforeMenuShow: function (menu) {
        var items = this.menuItems,
            len = items.length,
            item,
            prev;

        var needsSep = function (group, item) {
            return group.isXType('buttongroup') && !(item instanceof Ext.Toolbar.Separator);
        };

        this.clearMenu();
        menu.removeAll();

        for (var i = 0; i < len; i++) {
            item = items[i].component;

            if (prev && (needsSep(item, prev) || needsSep(prev, item))) {
                menu.add('-');
            }

            this.addComponentToMenu(menu, item);
            prev = item;
        }


        if (menu.items.length < 1) {
            menu.add(this.noItemsMenuText);
        }
    },


    createMenuConfig: function (component, hideOnClick) {
        var config = Ext.apply({}, component.initialConfig),
            group = component.toggleGroup;

        Ext.copyTo(config, component, [
            'iconCls', 'icon', 'itemId', 'disabled', 'handler', 'scope', 'menu'
        ]);

        Ext.apply(config, {
            text: component.overflowText || component.text,
            hideOnClick: hideOnClick
        });

        if (group || component.enableToggle) {
            Ext.apply(config, {
                group: group,
                checked: component.pressed,
                listeners: {
                    checkchange: function (item, checked) {
                        component.toggle(checked);
                    }
                }
            });
        }

        delete config.ownerCt;
        delete config.xtype;
        delete config.id;

        return config;
    },


    addComponentToMenu: function (menu, component) {
        if (component instanceof Ext.Toolbar.Separator) {
            menu.add('-');

        } else if (Ext.isFunction(component.isXType)) {
            if (component.isXType('splitbutton')) {
                menu.add(this.createMenuConfig(component, true));

            } else if (component.isXType('button')) {
                menu.add(this.createMenuConfig(component, !component.menu));

            } else if (component.isXType('buttongroup')) {
                component.items.each(function (item) {
                    this.addComponentToMenu(menu, item);
                }, this);
            }
        }
    },


    clearMenu: function () {
        var menu = this.moreMenu;
        if (menu && menu.items) {
            menu.items.each(function (item) {
                delete item.menu;
            });
        }
    },


    createMenu: function () {
        if (!this.menuTrigger) {
            this.createInnerElements();


            this.menu = new Ext.menu.Menu({
                ownerCt: this.layout.container,
                listeners: {
                    scope: this,
                    beforeshow: this.beforeMenuShow
                }
            });


            this.menuTrigger = new Ext.Button({
                iconCls: 'x-toolbar-more-icon',
                cls: 'x-toolbar-more',
                menu: this.menu,
                renderTo: this.afterCt
            });
        }
    },


    destroy: function () {
        Ext.destroy(this.menu, this.menuTrigger);
    }
});

Ext.layout.boxOverflow.menu = Ext.layout.boxOverflow.Menu;



Ext.layout.boxOverflow.HorizontalMenu = Ext.extend(Ext.layout.boxOverflow.Menu, {

    constructor: function () {
        Ext.layout.boxOverflow.HorizontalMenu.superclass.constructor.apply(this, arguments);

        var me = this,
            layout = me.layout,
            origFunction = layout.calculateChildBoxes;

        layout.calculateChildBoxes = function (visibleItems, targetSize) {
            var calcs = origFunction.apply(layout, arguments),
                meta = calcs.meta,
                items = me.menuItems;



            var hiddenWidth = 0;
            for (var index = 0, length = items.length; index < length; index++) {
                hiddenWidth += items[index].width;
            }

            meta.minimumWidth += hiddenWidth;
            meta.tooNarrow = meta.minimumWidth > targetSize.width;

            return calcs;
        };
    },

    handleOverflow: function (calculations, targetSize) {
        this.showTrigger();

        var newWidth = targetSize.width - this.afterCt.getWidth(),
            boxes = calculations.boxes,
            usedWidth = 0,
            recalculate = false;


        for (var index = 0, length = boxes.length; index < length; index++) {
            usedWidth += boxes[index].width;
        }

        var spareWidth = newWidth - usedWidth,
            showCount = 0;


        for (var index = 0, length = this.menuItems.length; index < length; index++) {
            var hidden = this.menuItems[index],
                comp = hidden.component,
                width = hidden.width;

            if (width < spareWidth) {
                comp.show();

                spareWidth -= width;
                showCount++;
                recalculate = true;
            } else {
                break;
            }
        }

        if (recalculate) {
            this.menuItems = this.menuItems.slice(showCount);
        } else {
            for (var i = boxes.length - 1; i >= 0; i--) {
                var item = boxes[i].component,
                    right = boxes[i].left + boxes[i].width;

                if (right >= newWidth) {
                    this.menuItems.unshift({
                        component: item,
                        width: boxes[i].width
                    });

                    item.hide();
                } else {
                    break;
                }
            }
        }

        if (this.menuItems.length == 0) {
            this.hideTrigger();
        }

        return {
            targetSize: {
                height: targetSize.height,
                width: newWidth
            },
            recalculate: recalculate
        };
    }
});

Ext.layout.boxOverflow.menu.hbox = Ext.layout.boxOverflow.HorizontalMenu;
Ext.layout.boxOverflow.Scroller = Ext.extend(Ext.layout.boxOverflow.None, {

    animateScroll: true,


    scrollIncrement: 100,


    wheelIncrement: 3,


    scrollRepeatInterval: 400,


    scrollDuration: 0.4,


    beforeCls: 'x-strip-left',


    afterCls: 'x-strip-right',


    scrollerCls: 'x-strip-scroller',


    beforeScrollerCls: 'x-strip-scroller-left',


    afterScrollerCls: 'x-strip-scroller-right',


    createWheelListener: function () {
        this.layout.innerCt.on({
            scope: this,
            mousewheel: function (e) {
                e.stopEvent();

                this.scrollBy(e.getWheelDelta() * this.wheelIncrement * -1, false);
            }
        });
    },


    handleOverflow: function (calculations, targetSize) {
        this.createInnerElements();
        this.showScrollers();
    },


    clearOverflow: function () {
        this.hideScrollers();
    },


    showScrollers: function () {
        this.createScrollers();

        this.beforeScroller.show();
        this.afterScroller.show();

        this.updateScrollButtons();
    },


    hideScrollers: function () {
        if (this.beforeScroller != undefined) {
            this.beforeScroller.hide();
            this.afterScroller.hide();
        }
    },


    createScrollers: function () {
        if (!this.beforeScroller && !this.afterScroller) {
            var before = this.beforeCt.createChild({
                cls: String.format("{0} {1} ", this.scrollerCls, this.beforeScrollerCls)
            });

            var after = this.afterCt.createChild({
                cls: String.format("{0} {1}", this.scrollerCls, this.afterScrollerCls)
            });

            before.addClassOnOver(this.beforeScrollerCls + '-hover');
            after.addClassOnOver(this.afterScrollerCls + '-hover');

            before.setVisibilityMode(Ext.Element.DISPLAY);
            after.setVisibilityMode(Ext.Element.DISPLAY);

            this.beforeRepeater = new Ext.util.ClickRepeater(before, {
                interval: this.scrollRepeatInterval,
                handler: this.scrollLeft,
                scope: this
            });

            this.afterRepeater = new Ext.util.ClickRepeater(after, {
                interval: this.scrollRepeatInterval,
                handler: this.scrollRight,
                scope: this
            });


            this.beforeScroller = before;


            this.afterScroller = after;
        }
    },


    destroy: function () {
        Ext.destroy(this.beforeScroller, this.afterScroller, this.beforeRepeater, this.afterRepeater, this.beforeCt, this.afterCt);
    },


    scrollBy: function (delta, animate) {
        this.scrollTo(this.getScrollPosition() + delta, animate);
    },


    getItem: function (item) {
        if (Ext.isString(item)) {
            item = Ext.getCmp(item);
        } else if (Ext.isNumber(item)) {
            item = this.items[item];
        }

        return item;
    },


    getScrollAnim: function () {
        return {
            duration: this.scrollDuration,
            callback: this.updateScrollButtons,
            scope: this
        };
    },


    updateScrollButtons: function () {
        if (this.beforeScroller == undefined || this.afterScroller == undefined) {
            return;
        }

        var beforeMeth = this.atExtremeBefore() ? 'addClass' : 'removeClass',
            afterMeth = this.atExtremeAfter() ? 'addClass' : 'removeClass',
            beforeCls = this.beforeScrollerCls + '-disabled',
            afterCls = this.afterScrollerCls + '-disabled';

        this.beforeScroller[beforeMeth](beforeCls);
        this.afterScroller[afterMeth](afterCls);
        this.scrolling = false;
    },


    atExtremeBefore: function () {
        return this.getScrollPosition() === 0;
    },


    scrollLeft: function (animate) {
        this.scrollBy(-this.scrollIncrement, animate);
    },


    scrollRight: function (animate) {
        this.scrollBy(this.scrollIncrement, animate);
    },


    scrollToItem: function (item, animate) {
        item = this.getItem(item);

        if (item != undefined) {
            var visibility = this.getItemVisibility(item);

            if (!visibility.fullyVisible) {
                var box = item.getBox(true, true),
                    newX = box.x;

                if (visibility.hiddenRight) {
                    newX -= (this.layout.innerCt.getWidth() - box.width);
                }

                this.scrollTo(newX, animate);
            }
        }
    },


    getItemVisibility: function (item) {
        var box = this.getItem(item).getBox(true, true),
            itemLeft = box.x,
            itemRight = box.x + box.width,
            scrollLeft = this.getScrollPosition(),
            scrollRight = this.layout.innerCt.getWidth() + scrollLeft;

        return {
            hiddenLeft: itemLeft < scrollLeft,
            hiddenRight: itemRight > scrollRight,
            fullyVisible: itemLeft > scrollLeft && itemRight < scrollRight
        };
    }
});

Ext.layout.boxOverflow.scroller = Ext.layout.boxOverflow.Scroller;



Ext.layout.boxOverflow.VerticalScroller = Ext.extend(Ext.layout.boxOverflow.Scroller, {
    scrollIncrement: 75,
    wheelIncrement: 2,

    handleOverflow: function (calculations, targetSize) {
        Ext.layout.boxOverflow.VerticalScroller.superclass.handleOverflow.apply(this, arguments);

        return {
            targetSize: {
                height: targetSize.height - (this.beforeCt.getHeight() + this.afterCt.getHeight()),
                width: targetSize.width
            }
        };
    },


    createInnerElements: function () {
        var target = this.layout.innerCt;



        if (!this.beforeCt) {
            this.beforeCt = target.insertSibling({ cls: this.beforeCls }, 'before');
            this.afterCt = target.insertSibling({ cls: this.afterCls }, 'after');

            this.createWheelListener();
        }
    },


    scrollTo: function (position, animate) {
        var oldPosition = this.getScrollPosition(),
            newPosition = position.constrain(0, this.getMaxScrollBottom());

        if (newPosition != oldPosition && !this.scrolling) {
            if (animate == undefined) {
                animate = this.animateScroll;
            }

            this.layout.innerCt.scrollTo('top', newPosition, animate ? this.getScrollAnim() : false);

            if (animate) {
                this.scrolling = true;
            } else {
                this.scrolling = false;
                this.updateScrollButtons();
            }
        }
    },


    getScrollPosition: function () {
        return parseInt(this.layout.innerCt.dom.scrollTop, 10) || 0;
    },


    getMaxScrollBottom: function () {
        return this.layout.innerCt.dom.scrollHeight - this.layout.innerCt.getHeight();
    },


    atExtremeAfter: function () {
        return this.getScrollPosition() >= this.getMaxScrollBottom();
    }
});

Ext.layout.boxOverflow.scroller.vbox = Ext.layout.boxOverflow.VerticalScroller;



Ext.layout.boxOverflow.HorizontalScroller = Ext.extend(Ext.layout.boxOverflow.Scroller, {
    handleOverflow: function (calculations, targetSize) {
        Ext.layout.boxOverflow.HorizontalScroller.superclass.handleOverflow.apply(this, arguments);

        return {
            targetSize: {
                height: targetSize.height,
                width: targetSize.width - (this.beforeCt.getWidth() + this.afterCt.getWidth())
            }
        };
    },


    createInnerElements: function () {
        var target = this.layout.innerCt;



        if (!this.beforeCt) {
            this.afterCt = target.insertSibling({ cls: this.afterCls }, 'before');
            this.beforeCt = target.insertSibling({ cls: this.beforeCls }, 'before');

            this.createWheelListener();
        }
    },


    scrollTo: function (position, animate) {
        var oldPosition = this.getScrollPosition(),
            newPosition = position.constrain(0, this.getMaxScrollRight());

        if (newPosition != oldPosition && !this.scrolling) {
            if (animate == undefined) {
                animate = this.animateScroll;
            }

            this.layout.innerCt.scrollTo('left', newPosition, animate ? this.getScrollAnim() : false);

            if (animate) {
                this.scrolling = true;
            } else {
                this.scrolling = false;
                this.updateScrollButtons();
            }
        }
    },


    getScrollPosition: function () {
        return parseInt(this.layout.innerCt.dom.scrollLeft, 10) || 0;
    },


    getMaxScrollRight: function () {
        return this.layout.innerCt.dom.scrollWidth - this.layout.innerCt.getWidth();
    },


    atExtremeAfter: function () {
        return this.getScrollPosition() >= this.getMaxScrollRight();
    }
});

Ext.layout.boxOverflow.scroller.hbox = Ext.layout.boxOverflow.HorizontalScroller;
Ext.layout.HBoxLayout = Ext.extend(Ext.layout.BoxLayout, {

    align: 'top',

    type: 'hbox',





    calculateChildBoxes: function (visibleItems, targetSize) {
        var visibleCount = visibleItems.length,

            padding = this.padding,
            topOffset = padding.top,
            leftOffset = padding.left,
            paddingVert = topOffset + padding.bottom,
            paddingHoriz = leftOffset + padding.right,

            width = targetSize.width - this.scrollOffset,
            height = targetSize.height,
            availHeight = Math.max(0, height - paddingVert),

            isStart = this.pack == 'start',
            isCenter = this.pack == 'center',
            isEnd = this.pack == 'end',

            nonFlexWidth = 0,
            maxHeight = 0,
            totalFlex = 0,
            desiredWidth = 0,
            minimumWidth = 0,


            boxes = [],


            child, childWidth, childHeight, childSize, childMargins, canLayout, i, calcs, flexedWidth,
            horizMargins, vertMargins, stretchHeight;


        for (i = 0; i < visibleCount; i++) {
            child = visibleItems[i];
            childHeight = child.height;
            childWidth = child.width;
            canLayout = !child.hasLayout && typeof child.doLayout == 'function';


            if (typeof childWidth != 'number') {


                if (child.flex && !childWidth) {
                    totalFlex += child.flex;


                } else {


                    if (!childWidth && canLayout) {
                        child.doLayout();
                    }

                    childSize = child.getSize();
                    childWidth = childSize.width;
                    childHeight = childSize.height;
                }
            }

            childMargins = child.margins;
            horizMargins = childMargins.left + childMargins.right;

            nonFlexWidth += horizMargins + (childWidth || 0);
            desiredWidth += horizMargins + (child.flex ? child.minWidth || 0 : childWidth);
            minimumWidth += horizMargins + (child.minWidth || childWidth || 0);


            if (typeof childHeight != 'number') {
                if (canLayout) {
                    child.doLayout();
                }
                childHeight = child.getHeight();
            }

            maxHeight = Math.max(maxHeight, childHeight + childMargins.top + childMargins.bottom);


            boxes.push({
                component: child,
                height: childHeight || undefined,
                width: childWidth || undefined
            });
        }

        var shortfall = desiredWidth - width,
            tooNarrow = minimumWidth > width;


        var availableWidth = Math.max(0, width - nonFlexWidth - paddingHoriz);

        if (tooNarrow) {
            for (i = 0; i < visibleCount; i++) {
                boxes[i].width = visibleItems[i].minWidth || visibleItems[i].width || boxes[i].width;
            }
        } else {


            if (shortfall > 0) {
                var minWidths = [];


                for (var index = 0, length = visibleCount; index < length; index++) {
                    var item = visibleItems[index],
                        minWidth = item.minWidth || 0;



                    if (item.flex) {
                        boxes[index].width = minWidth;
                    } else {
                        minWidths.push({
                            minWidth: minWidth,
                            available: boxes[index].width - minWidth,
                            index: index
                        });
                    }
                }


                minWidths.sort(function (a, b) {
                    return a.available > b.available ? 1 : -1;
                });


                for (var i = 0, length = minWidths.length; i < length; i++) {
                    var itemIndex = minWidths[i].index;

                    if (itemIndex == undefined) {
                        continue;
                    }

                    var item = visibleItems[itemIndex],
                        box = boxes[itemIndex],
                        oldWidth = box.width,
                        minWidth = item.minWidth,
                        newWidth = Math.max(minWidth, oldWidth - Math.ceil(shortfall / (length - i))),
                        reduction = oldWidth - newWidth;

                    boxes[itemIndex].width = newWidth;
                    shortfall -= reduction;
                }
            } else {

                var remainingWidth = availableWidth,
                    remainingFlex = totalFlex;


                for (i = 0; i < visibleCount; i++) {
                    child = visibleItems[i];
                    calcs = boxes[i];

                    childMargins = child.margins;
                    vertMargins = childMargins.top + childMargins.bottom;

                    if (isStart && child.flex && !child.width) {
                        flexedWidth = Math.ceil((child.flex / remainingFlex) * remainingWidth);
                        remainingWidth -= flexedWidth;
                        remainingFlex -= child.flex;

                        calcs.width = flexedWidth;
                        calcs.dirtySize = true;
                    }
                }
            }
        }

        if (isCenter) {
            leftOffset += availableWidth / 2;
        } else if (isEnd) {
            leftOffset += availableWidth;
        }


        for (i = 0; i < visibleCount; i++) {
            child = visibleItems[i];
            calcs = boxes[i];

            childMargins = child.margins;
            leftOffset += childMargins.left;
            vertMargins = childMargins.top + childMargins.bottom;

            calcs.left = leftOffset;
            calcs.top = topOffset + childMargins.top;

            switch (this.align) {
                case 'stretch':
                    stretchHeight = availHeight - vertMargins;
                    calcs.height = stretchHeight.constrain(child.minHeight || 0, child.maxHeight || 1000000);
                    calcs.dirtySize = true;
                    break;
                case 'stretchmax':
                    stretchHeight = maxHeight - vertMargins;
                    calcs.height = stretchHeight.constrain(child.minHeight || 0, child.maxHeight || 1000000);
                    calcs.dirtySize = true;
                    break;
                case 'middle':
                    var diff = availHeight - calcs.height - vertMargins;
                    if (diff > 0) {
                        calcs.top = topOffset + vertMargins + (diff / 2);
                    }
            }

            leftOffset += calcs.width + childMargins.right;
        }

        return {
            boxes: boxes,
            meta: {
                maxHeight: maxHeight,
                nonFlexWidth: nonFlexWidth,
                desiredWidth: desiredWidth,
                minimumWidth: minimumWidth,
                shortfall: desiredWidth - width,
                tooNarrow: tooNarrow
            }
        };
    }
});

Ext.Container.LAYOUTS.hbox = Ext.layout.HBoxLayout;
Ext.layout.VBoxLayout = Ext.extend(Ext.layout.BoxLayout, {

    align: 'left',
    type: 'vbox',






    calculateChildBoxes: function (visibleItems, targetSize) {
        var visibleCount = visibleItems.length,

            padding = this.padding,
            topOffset = padding.top,
            leftOffset = padding.left,
            paddingVert = topOffset + padding.bottom,
            paddingHoriz = leftOffset + padding.right,

            width = targetSize.width - this.scrollOffset,
            height = targetSize.height,
            availWidth = Math.max(0, width - paddingHoriz),

            isStart = this.pack == 'start',
            isCenter = this.pack == 'center',
            isEnd = this.pack == 'end',

            nonFlexHeight = 0,
            maxWidth = 0,
            totalFlex = 0,
            desiredHeight = 0,
            minimumHeight = 0,


            boxes = [],


            child, childWidth, childHeight, childSize, childMargins, canLayout, i, calcs, flexedWidth,
            horizMargins, vertMargins, stretchWidth;


        for (i = 0; i < visibleCount; i++) {
            child = visibleItems[i];
            childHeight = child.height;
            childWidth = child.width;
            canLayout = !child.hasLayout && typeof child.doLayout == 'function';


            if (typeof childHeight != 'number') {


                if (child.flex && !childHeight) {
                    totalFlex += child.flex;


                } else {


                    if (!childHeight && canLayout) {
                        child.doLayout();
                    }

                    childSize = child.getSize();
                    childWidth = childSize.width;
                    childHeight = childSize.height;
                }
            }

            childMargins = child.margins;
            vertMargins = childMargins.top + childMargins.bottom;

            nonFlexHeight += vertMargins + (childHeight || 0);
            desiredHeight += vertMargins + (child.flex ? child.minHeight || 0 : childHeight);
            minimumHeight += vertMargins + (child.minHeight || childHeight || 0);


            if (typeof childWidth != 'number') {
                if (canLayout) {
                    child.doLayout();
                }
                childWidth = child.getWidth();
            }

            maxWidth = Math.max(maxWidth, childWidth + childMargins.left + childMargins.right);


            boxes.push({
                component: child,
                height: childHeight || undefined,
                width: childWidth || undefined
            });
        }

        var shortfall = desiredHeight - height,
            tooNarrow = minimumHeight > height;


        var availableHeight = Math.max(0, (height - nonFlexHeight - paddingVert));

        if (tooNarrow) {
            for (i = 0, length = visibleCount; i < length; i++) {
                boxes[i].height = visibleItems[i].minHeight || visibleItems[i].height || boxes[i].height;
            }
        } else {


            if (shortfall > 0) {
                var minHeights = [];


                for (var index = 0, length = visibleCount; index < length; index++) {
                    var item = visibleItems[index],
                        minHeight = item.minHeight || 0;



                    if (item.flex) {
                        boxes[index].height = minHeight;
                    } else {
                        minHeights.push({
                            minHeight: minHeight,
                            available: boxes[index].height - minHeight,
                            index: index
                        });
                    }
                }


                minHeights.sort(function (a, b) {
                    return a.available > b.available ? 1 : -1;
                });


                for (var i = 0, length = minHeights.length; i < length; i++) {
                    var itemIndex = minHeights[i].index;

                    if (itemIndex == undefined) {
                        continue;
                    }

                    var item = visibleItems[itemIndex],
                        box = boxes[itemIndex],
                        oldHeight = box.height,
                        minHeight = item.minHeight,
                        newHeight = Math.max(minHeight, oldHeight - Math.ceil(shortfall / (length - i))),
                        reduction = oldHeight - newHeight;

                    boxes[itemIndex].height = newHeight;
                    shortfall -= reduction;
                }
            } else {

                var remainingHeight = availableHeight,
                    remainingFlex = totalFlex;


                for (i = 0; i < visibleCount; i++) {
                    child = visibleItems[i];
                    calcs = boxes[i];

                    childMargins = child.margins;
                    horizMargins = childMargins.left + childMargins.right;

                    if (isStart && child.flex && !child.height) {
                        flexedHeight = Math.ceil((child.flex / remainingFlex) * remainingHeight);
                        remainingHeight -= flexedHeight;
                        remainingFlex -= child.flex;

                        calcs.height = flexedHeight;
                        calcs.dirtySize = true;
                    }
                }
            }
        }

        if (isCenter) {
            topOffset += availableHeight / 2;
        } else if (isEnd) {
            topOffset += availableHeight;
        }


        for (i = 0; i < visibleCount; i++) {
            child = visibleItems[i];
            calcs = boxes[i];

            childMargins = child.margins;
            topOffset += childMargins.top;
            horizMargins = childMargins.left + childMargins.right;


            calcs.left = leftOffset + childMargins.left;
            calcs.top = topOffset;

            switch (this.align) {
                case 'stretch':
                    stretchWidth = availWidth - horizMargins;
                    calcs.width = stretchWidth.constrain(child.minWidth || 0, child.maxWidth || 1000000);
                    calcs.dirtySize = true;
                    break;
                case 'stretchmax':
                    stretchWidth = maxWidth - horizMargins;
                    calcs.width = stretchWidth.constrain(child.minWidth || 0, child.maxWidth || 1000000);
                    calcs.dirtySize = true;
                    break;
                case 'center':
                    var diff = availWidth - calcs.width - horizMargins;
                    if (diff > 0) {
                        calcs.left = leftOffset + horizMargins + (diff / 2);
                    }
            }

            topOffset += calcs.height + childMargins.bottom;
        }

        return {
            boxes: boxes,
            meta: {
                maxWidth: maxWidth,
                nonFlexHeight: nonFlexHeight,
                desiredHeight: desiredHeight,
                minimumHeight: minimumHeight,
                shortfall: desiredHeight - height,
                tooNarrow: tooNarrow
            }
        };
    }
});

Ext.Container.LAYOUTS.vbox = Ext.layout.VBoxLayout;

Ext.layout.ToolbarLayout = Ext.extend(Ext.layout.ContainerLayout, {
    monitorResize: true,

    type: 'toolbar',


    triggerWidth: 18,


    noItemsMenuText: '<div class="x-toolbar-no-items">(None)</div>',


    lastOverflow: false,


    tableHTML: [
        '<table cellspacing="0" class="x-toolbar-ct">',
            '<tbody>',
                '<tr>',
                    '<td class="x-toolbar-left" align="{0}">',
                        '<table cellspacing="0">',
                            '<tbody>',
                                '<tr class="x-toolbar-left-row"></tr>',
                            '</tbody>',
                        '</table>',
                    '</td>',
                    '<td class="x-toolbar-right" align="right">',
                        '<table cellspacing="0" class="x-toolbar-right-ct">',
                            '<tbody>',
                                '<tr>',
                                    '<td>',
                                        '<table cellspacing="0">',
                                            '<tbody>',
                                                '<tr class="x-toolbar-right-row"></tr>',
                                            '</tbody>',
                                        '</table>',
                                    '</td>',
                                    '<td>',
                                        '<table cellspacing="0">',
                                            '<tbody>',
                                                '<tr class="x-toolbar-extras-row"></tr>',
                                            '</tbody>',
                                        '</table>',
                                    '</td>',
                                '</tr>',
                            '</tbody>',
                        '</table>',
                    '</td>',
                '</tr>',
            '</tbody>',
        '</table>'
    ].join(""),


    onLayout: function (ct, target) {

        if (!this.leftTr) {
            var align = ct.buttonAlign == 'center' ? 'center' : 'left';

            target.addClass('x-toolbar-layout-ct');
            target.insertHtml('beforeEnd', String.format(this.tableHTML, align));

            this.leftTr = target.child('tr.x-toolbar-left-row', true);
            this.rightTr = target.child('tr.x-toolbar-right-row', true);
            this.extrasTr = target.child('tr.x-toolbar-extras-row', true);

            if (this.hiddenItem == undefined) {

                this.hiddenItems = [];
            }
        }

        var side = ct.buttonAlign == 'right' ? this.rightTr : this.leftTr,
            items = ct.items.items,
            position = 0;


        for (var i = 0, len = items.length, c; i < len; i++, position++) {
            c = items[i];

            if (c.isFill) {
                side = this.rightTr;
                position = -1;
            } else if (!c.rendered) {
                c.render(this.insertCell(c, side, position));
                this.configureItem(c);
            } else {
                if (!c.xtbHidden && !this.isValidParent(c, side.childNodes[position])) {
                    var td = this.insertCell(c, side, position);
                    td.appendChild(c.getPositionEl().dom);
                    c.container = Ext.get(td);
                }
            }
        }


        this.cleanup(this.leftTr);
        this.cleanup(this.rightTr);
        this.cleanup(this.extrasTr);
        this.fitToSize(target);
    },


    cleanup: function (el) {
        var cn = el.childNodes, i, c;

        for (i = cn.length - 1; i >= 0 && (c = cn[i]); i--) {
            if (!c.firstChild) {
                el.removeChild(c);
            }
        }
    },


    insertCell: function (c, target, position) {
        var td = document.createElement('td');
        td.className = 'x-toolbar-cell';

        target.insertBefore(td, target.childNodes[position] || null);

        return td;
    },


    hideItem: function (item) {
        this.hiddenItems.push(item);

        item.xtbHidden = true;
        item.xtbWidth = item.getPositionEl().dom.parentNode.offsetWidth;
        item.hide();
    },


    unhideItem: function (item) {
        item.show();
        item.xtbHidden = false;
        this.hiddenItems.remove(item);
    },


    getItemWidth: function (c) {
        return c.hidden ? (c.xtbWidth || 0) : c.getPositionEl().dom.parentNode.offsetWidth;
    },


    fitToSize: function (target) {
        if (this.container.enableOverflow === false) {
            return;
        }

        var width = target.dom.clientWidth,
            tableWidth = target.dom.firstChild.offsetWidth,
            clipWidth = width - this.triggerWidth,
            lastWidth = this.lastWidth || 0,

            hiddenItems = this.hiddenItems,
            hasHiddens = hiddenItems.length != 0,
            isLarger = width >= lastWidth;

        this.lastWidth = width;

        if (tableWidth > width || (hasHiddens && isLarger)) {
            var items = this.container.items.items,
                len = items.length,
                loopWidth = 0,
                item;

            for (var i = 0; i < len; i++) {
                item = items[i];

                if (!item.isFill) {
                    loopWidth += this.getItemWidth(item);
                    if (loopWidth > clipWidth) {
                        if (!(item.hidden || item.xtbHidden)) {
                            this.hideItem(item);
                        }
                    } else if (item.xtbHidden) {
                        this.unhideItem(item);
                    }
                }
            }
        }


        hasHiddens = hiddenItems.length != 0;

        if (hasHiddens) {
            this.initMore();

            if (!this.lastOverflow) {
                this.container.fireEvent('overflowchange', this.container, true);
                this.lastOverflow = true;
            }
        } else if (this.more) {
            this.clearMenu();
            this.more.destroy();
            delete this.more;

            if (this.lastOverflow) {
                this.container.fireEvent('overflowchange', this.container, false);
                this.lastOverflow = false;
            }
        }
    },


    createMenuConfig: function (component, hideOnClick) {
        var config = Ext.apply({}, component.initialConfig),
            group = component.toggleGroup;

        Ext.copyTo(config, component, [
            'iconCls', 'icon', 'itemId', 'disabled', 'handler', 'scope', 'menu'
        ]);

        Ext.apply(config, {
            text: component.overflowText || component.text,
            hideOnClick: hideOnClick
        });

        if (group || component.enableToggle) {
            Ext.apply(config, {
                group: group,
                checked: component.pressed,
                listeners: {
                    checkchange: function (item, checked) {
                        component.toggle(checked);
                    }
                }
            });
        }

        delete config.ownerCt;
        delete config.xtype;
        delete config.id;

        return config;
    },


    addComponentToMenu: function (menu, component) {
        if (component instanceof Ext.Toolbar.Separator) {
            menu.add('-');

        } else if (Ext.isFunction(component.isXType)) {
            if (component.isXType('splitbutton')) {
                menu.add(this.createMenuConfig(component, true));

            } else if (component.isXType('button')) {
                menu.add(this.createMenuConfig(component, !component.menu));

            } else if (component.isXType('buttongroup')) {
                component.items.each(function (item) {
                    this.addComponentToMenu(menu, item);
                }, this);
            }
        }
    },


    clearMenu: function () {
        var menu = this.moreMenu;
        if (menu && menu.items) {
            menu.items.each(function (item) {
                delete item.menu;
            });
        }
    },


    beforeMoreShow: function (menu) {
        var items = this.container.items.items,
            len = items.length,
            item,
            prev;

        var needsSep = function (group, item) {
            return group.isXType('buttongroup') && !(item instanceof Ext.Toolbar.Separator);
        };

        this.clearMenu();
        menu.removeAll();
        for (var i = 0; i < len; i++) {
            item = items[i];
            if (item.xtbHidden) {
                if (prev && (needsSep(item, prev) || needsSep(prev, item))) {
                    menu.add('-');
                }
                this.addComponentToMenu(menu, item);
                prev = item;
            }
        }


        if (menu.items.length < 1) {
            menu.add(this.noItemsMenuText);
        }
    },


    initMore: function () {
        if (!this.more) {

            this.moreMenu = new Ext.menu.Menu({
                ownerCt: this.container,
                listeners: {
                    beforeshow: this.beforeMoreShow,
                    scope: this
                }
            });


            this.more = new Ext.Button({
                iconCls: 'x-toolbar-more-icon',
                cls: 'x-toolbar-more',
                menu: this.moreMenu,
                ownerCt: this.container
            });

            var td = this.insertCell(this.more, this.extrasTr, 100);
            this.more.render(td);
        }
    },

    destroy: function () {
        Ext.destroy(this.more, this.moreMenu);
        delete this.leftTr;
        delete this.rightTr;
        delete this.extrasTr;
        Ext.layout.ToolbarLayout.superclass.destroy.call(this);
    }
});

Ext.Container.LAYOUTS.toolbar = Ext.layout.ToolbarLayout;

Ext.layout.MenuLayout = Ext.extend(Ext.layout.ContainerLayout, {
    monitorResize: true,

    type: 'menu',

    setContainer: function (ct) {
        this.monitorResize = !ct.floating;


        ct.on('autosize', this.doAutoSize, this);
        Ext.layout.MenuLayout.superclass.setContainer.call(this, ct);
    },

    renderItem: function (c, position, target) {
        if (!this.itemTpl) {
            this.itemTpl = Ext.layout.MenuLayout.prototype.itemTpl = new Ext.XTemplate(
                '<li id="{itemId}" class="{itemCls}">',
                    '<tpl if="needsIcon">',
                        '<img alt="{altText}" src="{icon}" class="{iconCls}"/>',
                    '</tpl>',
                '</li>'
            );
        }

        if (c && !c.rendered) {
            if (Ext.isNumber(position)) {
                position = target.dom.childNodes[position];
            }
            var a = this.getItemArgs(c);


            c.render(c.positionEl = position ?
                this.itemTpl.insertBefore(position, a, true) :
                this.itemTpl.append(target, a, true));


            c.positionEl.menuItemId = c.getItemId();



            if (!a.isMenuItem && a.needsIcon) {
                c.positionEl.addClass('x-menu-list-item-indent');
            }
            this.configureItem(c);
        } else if (c && !this.isValidParent(c, target)) {
            if (Ext.isNumber(position)) {
                position = target.dom.childNodes[position];
            }
            target.dom.insertBefore(c.getActionEl().dom, position || null);
        }
    },

    getItemArgs: function (c) {
        var isMenuItem = c instanceof Ext.menu.Item,
            canHaveIcon = !(isMenuItem || c instanceof Ext.menu.Separator);

        return {
            isMenuItem: isMenuItem,
            needsIcon: canHaveIcon && (c.icon || c.iconCls),
            icon: c.icon || Ext.BLANK_IMAGE_URL,
            iconCls: 'x-menu-item-icon ' + (c.iconCls || ''),
            itemId: 'x-menu-el-' + c.id,
            itemCls: 'x-menu-list-item ',
            altText: c.altText || ''
        };
    },


    isValidParent: function (c, target) {
        return c.el.up('li.x-menu-list-item', 5).dom.parentNode === (target.dom || target);
    },

    onLayout: function (ct, target) {
        Ext.layout.MenuLayout.superclass.onLayout.call(this, ct, target);
        this.doAutoSize();
    },

    doAutoSize: function () {
        var ct = this.container, w = ct.width;
        if (ct.floating) {
            if (w) {
                ct.setWidth(w);
            } else if (Ext.isIE) {
                ct.setWidth(Ext.isStrict && (Ext.isIE7 || Ext.isIE8) ? 'auto' : ct.minWidth);
                var el = ct.getEl(), t = el.dom.offsetWidth;
                ct.setWidth(ct.getLayoutTarget().getWidth() + el.getFrameWidth('lr'));
            }
        }
    }
});
Ext.Container.LAYOUTS['menu'] = Ext.layout.MenuLayout;

Ext.Viewport = Ext.extend(Ext.Container, {













    initComponent: function () {
        Ext.Viewport.superclass.initComponent.call(this);
        document.getElementsByTagName('html')[0].className += ' x-viewport';
        this.el = Ext.getBody();
        this.el.setHeight = Ext.emptyFn;
        this.el.setWidth = Ext.emptyFn;
        this.el.setSize = Ext.emptyFn;
        this.el.dom.scroll = 'no';
        this.allowDomMove = false;
        this.autoWidth = true;
        this.autoHeight = true;
        Ext.EventManager.onWindowResize(this.fireResize, this);
        this.renderTo = this.el;
    },

    fireResize: function (w, h) {
        this.fireEvent('resize', this, w, h, w, h);
    }
});
Ext.reg('viewport', Ext.Viewport);

Ext.Panel = Ext.extend(Ext.Container, {












































    baseCls: 'x-panel',

    collapsedCls: 'x-panel-collapsed',

    maskDisabled: true,

    animCollapse: Ext.enableFx,

    headerAsText: true,

    buttonAlign: 'right',

    collapsed: false,

    collapseFirst: true,

    minButtonWidth: 75,


    elements: 'body',

    preventBodyReset: false,


    padding: undefined,


    resizeEvent: 'bodyresize',




    toolTarget: 'header',
    collapseEl: 'bwrap',
    slideAnchor: 't',
    disabledClass: '',


    deferHeight: true,

    expandDefaults: {
        duration: 0.25
    },

    collapseDefaults: {
        duration: 0.25
    },


    initComponent: function () {
        Ext.Panel.superclass.initComponent.call(this);

        this.addEvents(

            'bodyresize',

            'titlechange',

            'iconchange',

            'collapse',

            'expand',

            'beforecollapse',

            'beforeexpand',

            'beforeclose',

            'close',

            'activate',

            'deactivate'
        );

        if (this.unstyled) {
            this.baseCls = 'x-plain';
        }


        this.toolbars = [];

        if (this.tbar) {
            this.elements += ',tbar';
            this.topToolbar = this.createToolbar(this.tbar);
            this.tbar = null;

        }
        if (this.bbar) {
            this.elements += ',bbar';
            this.bottomToolbar = this.createToolbar(this.bbar);
            this.bbar = null;
        }

        if (this.header === true) {
            this.elements += ',header';
            this.header = null;
        } else if (this.headerCfg || (this.title && this.header !== false)) {
            this.elements += ',header';
        }

        if (this.footerCfg || this.footer === true) {
            this.elements += ',footer';
            this.footer = null;
        }

        if (this.buttons) {
            this.fbar = this.buttons;
            this.buttons = null;
        }
        if (this.fbar) {
            this.createFbar(this.fbar);
        }
        if (this.autoLoad) {
            this.on('render', this.doAutoLoad, this, { delay: 10 });
        }
    },


    createFbar: function (fbar) {
        var min = this.minButtonWidth;
        this.elements += ',footer';
        this.fbar = this.createToolbar(fbar, {
            buttonAlign: this.buttonAlign,
            toolbarCls: 'x-panel-fbar',
            enableOverflow: false,
            defaults: function (c) {
                return {
                    minWidth: c.minWidth || min
                };
            }
        });



        this.fbar.items.each(function (c) {
            c.minWidth = c.minWidth || this.minButtonWidth;
        }, this);
        this.buttons = this.fbar.items.items;
    },


    createToolbar: function (tb, options) {
        var result;

        if (Ext.isArray(tb)) {
            tb = {
                items: tb
            };
        }
        result = tb.events ? Ext.apply(tb, options) : this.createComponent(Ext.apply({}, tb, options), 'toolbar');
        this.toolbars.push(result);
        return result;
    },


    createElement: function (name, pnode) {
        if (this[name]) {
            pnode.appendChild(this[name].dom);
            return;
        }

        if (name === 'bwrap' || this.elements.indexOf(name) != -1) {
            if (this[name + 'Cfg']) {
                this[name] = Ext.fly(pnode).createChild(this[name + 'Cfg']);
            } else {
                var el = document.createElement('div');
                el.className = this[name + 'Cls'];
                this[name] = Ext.get(pnode.appendChild(el));
            }
            if (this[name + 'CssClass']) {
                this[name].addClass(this[name + 'CssClass']);
            }
            if (this[name + 'Style']) {
                this[name].applyStyles(this[name + 'Style']);
            }
        }
    },


    onRender: function (ct, position) {
        Ext.Panel.superclass.onRender.call(this, ct, position);
        this.createClasses();

        var el = this.el,
            d = el.dom,
            bw,
            ts;


        if (this.collapsible && !this.hideCollapseTool) {
            this.tools = this.tools ? this.tools.slice(0) : [];
            this.tools[this.collapseFirst ? 'unshift' : 'push']({
                id: 'toggle',
                handler: this.toggleCollapse,
                scope: this
            });
        }

        if (this.tools) {
            ts = this.tools;
            this.elements += (this.header !== false) ? ',header' : '';
        }
        this.tools = {};

        el.addClass(this.baseCls);
        if (d.firstChild) {
            this.header = el.down('.' + this.headerCls);
            this.bwrap = el.down('.' + this.bwrapCls);
            var cp = this.bwrap ? this.bwrap : el;
            this.tbar = cp.down('.' + this.tbarCls);
            this.body = cp.down('.' + this.bodyCls);
            this.bbar = cp.down('.' + this.bbarCls);
            this.footer = cp.down('.' + this.footerCls);
            this.fromMarkup = true;
        }
        if (this.preventBodyReset === true) {
            el.addClass('x-panel-reset');
        }
        if (this.cls) {
            el.addClass(this.cls);
        }

        if (this.buttons) {
            this.elements += ',footer';
        }




        if (this.frame) {
            el.insertHtml('afterBegin', String.format(Ext.Element.boxMarkup, this.baseCls));

            this.createElement('header', d.firstChild.firstChild.firstChild);
            this.createElement('bwrap', d);


            bw = this.bwrap.dom;
            var ml = d.childNodes[1], bl = d.childNodes[2];
            bw.appendChild(ml);
            bw.appendChild(bl);

            var mc = bw.firstChild.firstChild.firstChild;
            this.createElement('tbar', mc);
            this.createElement('body', mc);
            this.createElement('bbar', mc);
            this.createElement('footer', bw.lastChild.firstChild.firstChild);

            if (!this.footer) {
                this.bwrap.dom.lastChild.className += ' x-panel-nofooter';
            }

            this.ft = Ext.get(this.bwrap.dom.lastChild);
            this.mc = Ext.get(mc);
        } else {
            this.createElement('header', d);
            this.createElement('bwrap', d);


            bw = this.bwrap.dom;
            this.createElement('tbar', bw);
            this.createElement('body', bw);
            this.createElement('bbar', bw);
            this.createElement('footer', bw);

            if (!this.header) {
                this.body.addClass(this.bodyCls + '-noheader');
                if (this.tbar) {
                    this.tbar.addClass(this.tbarCls + '-noheader');
                }
            }
        }

        if (Ext.isDefined(this.padding)) {
            this.body.setStyle('padding', this.body.addUnits(this.padding));
        }

        if (this.border === false) {
            this.el.addClass(this.baseCls + '-noborder');
            this.body.addClass(this.bodyCls + '-noborder');
            if (this.header) {
                this.header.addClass(this.headerCls + '-noborder');
            }
            if (this.footer) {
                this.footer.addClass(this.footerCls + '-noborder');
            }
            if (this.tbar) {
                this.tbar.addClass(this.tbarCls + '-noborder');
            }
            if (this.bbar) {
                this.bbar.addClass(this.bbarCls + '-noborder');
            }
        }

        if (this.bodyBorder === false) {
            this.body.addClass(this.bodyCls + '-noborder');
        }

        this.bwrap.enableDisplayMode('block');

        if (this.header) {
            this.header.unselectable();


            if (this.headerAsText) {
                this.header.dom.innerHTML =
                    '<span class="' + this.headerTextCls + '">' + this.header.dom.innerHTML + '</span>';

                if (this.iconCls) {
                    this.setIconClass(this.iconCls);
                }
            }
        }

        if (this.floating) {
            this.makeFloating(this.floating);
        }

        if (this.collapsible && this.titleCollapse && this.header) {
            this.mon(this.header, 'click', this.toggleCollapse, this);
            this.header.setStyle('cursor', 'pointer');
        }
        if (ts) {
            this.addTool.apply(this, ts);
        }


        if (this.fbar) {
            this.footer.addClass('x-panel-btns');
            this.fbar.ownerCt = this;
            this.fbar.render(this.footer);
            this.footer.createChild({ cls: 'x-clear' });
        }
        if (this.tbar && this.topToolbar) {
            this.topToolbar.ownerCt = this;
            this.topToolbar.render(this.tbar);
        }
        if (this.bbar && this.bottomToolbar) {
            this.bottomToolbar.ownerCt = this;
            this.bottomToolbar.render(this.bbar);
        }
    },


    setIconClass: function (cls) {
        var old = this.iconCls;
        this.iconCls = cls;
        if (this.rendered && this.header) {
            if (this.frame) {
                this.header.addClass('x-panel-icon');
                this.header.replaceClass(old, this.iconCls);
            } else {
                var hd = this.header,
                    img = hd.child('img.x-panel-inline-icon');
                if (img) {
                    Ext.fly(img).replaceClass(old, this.iconCls);
                } else {
                    var hdspan = hd.child('span.' + this.headerTextCls);
                    if (hdspan) {
                        Ext.DomHelper.insertBefore(hdspan.dom, {
                            tag: 'img', alt: '', src: Ext.BLANK_IMAGE_URL, cls: 'x-panel-inline-icon ' + this.iconCls
                        });
                    }
                }
            }
        }
        this.fireEvent('iconchange', this, cls, old);
    },


    makeFloating: function (cfg) {
        this.floating = true;
        this.el = new Ext.Layer(Ext.apply({}, cfg, {
            shadow: Ext.isDefined(this.shadow) ? this.shadow : 'sides',
            shadowOffset: this.shadowOffset,
            constrain: false,
            shim: this.shim === false ? false : undefined
        }), this.el);
    },


    getTopToolbar: function () {
        return this.topToolbar;
    },


    getBottomToolbar: function () {
        return this.bottomToolbar;
    },


    getFooterToolbar: function () {
        return this.fbar;
    },


    addButton: function (config, handler, scope) {
        if (!this.fbar) {
            this.createFbar([]);
        }
        if (handler) {
            if (Ext.isString(config)) {
                config = { text: config };
            }
            config = Ext.apply({
                handler: handler,
                scope: scope
            }, config);
        }
        return this.fbar.add(config);
    },


    addTool: function () {
        if (!this.rendered) {
            if (!this.tools) {
                this.tools = [];
            }
            Ext.each(arguments, function (arg) {
                this.tools.push(arg);
            }, this);
            return;
        }

        if (!this[this.toolTarget]) {
            return;
        }
        if (!this.toolTemplate) {

            var tt = new Ext.Template(
                 '<div class="x-tool x-tool-{id}">&#160;</div>'
            );
            tt.disableFormats = true;
            tt.compile();
            Ext.Panel.prototype.toolTemplate = tt;
        }
        for (var i = 0, a = arguments, len = a.length; i < len; i++) {
            var tc = a[i];
            if (!this.tools[tc.id]) {
                var overCls = 'x-tool-' + tc.id + '-over';
                var t = this.toolTemplate.insertFirst(this[this.toolTarget], tc, true);
                this.tools[tc.id] = t;
                t.enableDisplayMode('block');
                this.mon(t, 'click', this.createToolHandler(t, tc, overCls, this));
                if (tc.on) {
                    this.mon(t, tc.on);
                }
                if (tc.hidden) {
                    t.hide();
                }
                if (tc.qtip) {
                    if (Ext.isObject(tc.qtip)) {
                        Ext.QuickTips.register(Ext.apply({
                            target: t.id
                        }, tc.qtip));
                    } else {
                        t.dom.qtip = tc.qtip;
                    }
                }
                t.addClassOnOver(overCls);
            }
        }
    },

    onLayout: function (shallow, force) {
        Ext.Panel.superclass.onLayout.apply(this, arguments);
        if (this.hasLayout && this.toolbars.length > 0) {
            Ext.each(this.toolbars, function (tb) {
                tb.doLayout(undefined, force);
            });
            this.syncHeight();
        }
    },

    syncHeight: function () {
        var h = this.toolbarHeight,
                bd = this.body,
                lsh = this.lastSize.height,
                sz;

        if (this.autoHeight || !Ext.isDefined(lsh) || lsh == 'auto') {
            return;
        }


        if (h != this.getToolbarHeight()) {
            h = Math.max(0, lsh - this.getFrameHeight());
            bd.setHeight(h);
            sz = bd.getSize();
            this.toolbarHeight = this.getToolbarHeight();
            this.onBodyResize(sz.width, sz.height);
        }
    },


    onShow: function () {
        if (this.floating) {
            return this.el.show();
        }
        Ext.Panel.superclass.onShow.call(this);
    },


    onHide: function () {
        if (this.floating) {
            return this.el.hide();
        }
        Ext.Panel.superclass.onHide.call(this);
    },


    createToolHandler: function (t, tc, overCls, panel) {
        return function (e) {
            t.removeClass(overCls);
            if (tc.stopEvent !== false) {
                e.stopEvent();
            }
            if (tc.handler) {
                tc.handler.call(tc.scope || t, e, t, panel, tc);
            }
        };
    },


    afterRender: function () {
        if (this.floating && !this.hidden) {
            this.el.show();
        }
        if (this.title) {
            this.setTitle(this.title);
        }
        Ext.Panel.superclass.afterRender.call(this);
        if (this.collapsed) {
            this.collapsed = false;
            this.collapse(false);
        }
        this.initEvents();
    },


    getKeyMap: function () {
        if (!this.keyMap) {
            this.keyMap = new Ext.KeyMap(this.el, this.keys);
        }
        return this.keyMap;
    },


    initEvents: function () {
        if (this.keys) {
            this.getKeyMap();
        }
        if (this.draggable) {
            this.initDraggable();
        }
        if (this.toolbars.length > 0) {
            Ext.each(this.toolbars, function (tb) {
                tb.doLayout();
                tb.on({
                    scope: this,
                    afterlayout: this.syncHeight,
                    remove: this.syncHeight
                });
            }, this);
            this.syncHeight();
        }

    },


    initDraggable: function () {

        this.dd = new Ext.Panel.DD(this, Ext.isBoolean(this.draggable) ? null : this.draggable);
    },


    beforeEffect: function (anim) {
        if (this.floating) {
            this.el.beforeAction();
        }
        if (anim !== false) {
            this.el.addClass('x-panel-animated');
        }
    },


    afterEffect: function (anim) {
        this.syncShadow();
        this.el.removeClass('x-panel-animated');
    },


    createEffect: function (a, cb, scope) {
        var o = {
            scope: scope,
            block: true
        };
        if (a === true) {
            o.callback = cb;
            return o;
        } else if (!a.callback) {
            o.callback = cb;
        } else {
            o.callback = function () {
                cb.call(scope);
                Ext.callback(a.callback, a.scope);
            };
        }
        return Ext.applyIf(o, a);
    },


    collapse: function (animate) {
        if (this.collapsed || this.el.hasFxBlock() || this.fireEvent('beforecollapse', this, animate) === false) {
            return;
        }
        var doAnim = animate === true || (animate !== false && this.animCollapse);
        this.beforeEffect(doAnim);
        this.onCollapse(doAnim, animate);
        return this;
    },


    onCollapse: function (doAnim, animArg) {
        if (doAnim) {
            this[this.collapseEl].slideOut(this.slideAnchor,
                    Ext.apply(this.createEffect(animArg || true, this.afterCollapse, this),
                        this.collapseDefaults));
        } else {
            this[this.collapseEl].hide(this.hideMode);
            this.afterCollapse(false);
        }
    },


    afterCollapse: function (anim) {
        this.collapsed = true;
        this.el.addClass(this.collapsedCls);
        if (anim !== false) {
            this[this.collapseEl].hide(this.hideMode);
        }
        this.afterEffect(anim);


        this.cascade(function (c) {
            if (c.lastSize) {
                c.lastSize = { width: undefined, height: undefined };
            }
        });
        this.fireEvent('collapse', this);
    },


    expand: function (animate) {
        if (!this.collapsed || this.el.hasFxBlock() || this.fireEvent('beforeexpand', this, animate) === false) {
            return;
        }
        var doAnim = animate === true || (animate !== false && this.animCollapse);
        this.el.removeClass(this.collapsedCls);
        this.beforeEffect(doAnim);
        this.onExpand(doAnim, animate);
        return this;
    },


    onExpand: function (doAnim, animArg) {
        if (doAnim) {
            this[this.collapseEl].slideIn(this.slideAnchor,
                    Ext.apply(this.createEffect(animArg || true, this.afterExpand, this),
                        this.expandDefaults));
        } else {
            this[this.collapseEl].show(this.hideMode);
            this.afterExpand(false);
        }
    },


    afterExpand: function (anim) {
        this.collapsed = false;
        if (anim !== false) {
            this[this.collapseEl].show(this.hideMode);
        }
        this.afterEffect(anim);
        if (this.deferLayout) {
            delete this.deferLayout;
            this.doLayout(true);
        }
        this.fireEvent('expand', this);
    },


    toggleCollapse: function (animate) {
        this[this.collapsed ? 'expand' : 'collapse'](animate);
        return this;
    },


    onDisable: function () {
        if (this.rendered && this.maskDisabled) {
            this.el.mask();
        }
        Ext.Panel.superclass.onDisable.call(this);
    },


    onEnable: function () {
        if (this.rendered && this.maskDisabled) {
            this.el.unmask();
        }
        Ext.Panel.superclass.onEnable.call(this);
    },


    onResize: function (adjWidth, adjHeight, rawWidth, rawHeight) {
        var w = adjWidth,
            h = adjHeight;

        if (Ext.isDefined(w) || Ext.isDefined(h)) {
            if (!this.collapsed) {




                if (Ext.isNumber(w)) {
                    this.body.setWidth(w = this.adjustBodyWidth(w - this.getFrameWidth()));
                } else if (w == 'auto') {
                    w = this.body.setWidth('auto').dom.offsetWidth;
                } else {
                    w = this.body.dom.offsetWidth;
                }

                if (this.tbar) {
                    this.tbar.setWidth(w);
                    if (this.topToolbar) {
                        this.topToolbar.setSize(w);
                    }
                }
                if (this.bbar) {
                    this.bbar.setWidth(w);
                    if (this.bottomToolbar) {
                        this.bottomToolbar.setSize(w);

                        if (Ext.isIE) {
                            this.bbar.setStyle('position', 'static');
                            this.bbar.setStyle('position', '');
                        }
                    }
                }
                if (this.footer) {
                    this.footer.setWidth(w);
                    if (this.fbar) {
                        this.fbar.setSize(Ext.isIE ? (w - this.footer.getFrameWidth('lr')) : 'auto');
                    }
                }


                if (Ext.isNumber(h)) {
                    h = Math.max(0, h - this.getFrameHeight());

                    this.body.setHeight(h);
                } else if (h == 'auto') {
                    this.body.setHeight(h);
                }

                if (this.disabled && this.el._mask) {
                    this.el._mask.setSize(this.el.dom.clientWidth, this.el.getHeight());
                }
            } else {

                this.queuedBodySize = { width: w, height: h };
                if (!this.queuedExpand && this.allowQueuedExpand !== false) {
                    this.queuedExpand = true;
                    this.on('expand', function () {
                        delete this.queuedExpand;
                        this.onResize(this.queuedBodySize.width, this.queuedBodySize.height);
                    }, this, { single: true });
                }
            }
            this.onBodyResize(w, h);
        }
        this.syncShadow();
        Ext.Panel.superclass.onResize.call(this, adjWidth, adjHeight, rawWidth, rawHeight);

    },


    onBodyResize: function (w, h) {
        this.fireEvent('bodyresize', this, w, h);
    },


    getToolbarHeight: function () {
        var h = 0;
        if (this.rendered) {
            Ext.each(this.toolbars, function (tb) {
                h += tb.getHeight();
            }, this);
        }
        return h;
    },


    adjustBodyHeight: function (h) {
        return h;
    },


    adjustBodyWidth: function (w) {
        return w;
    },


    onPosition: function () {
        this.syncShadow();
    },


    getFrameWidth: function () {
        var w = this.el.getFrameWidth('lr') + this.bwrap.getFrameWidth('lr');

        if (this.frame) {
            var l = this.bwrap.dom.firstChild;
            w += (Ext.fly(l).getFrameWidth('l') + Ext.fly(l.firstChild).getFrameWidth('r'));
            w += this.mc.getFrameWidth('lr');
        }
        return w;
    },


    getFrameHeight: function () {
        var h = this.el.getFrameWidth('tb') + this.bwrap.getFrameWidth('tb');
        h += (this.tbar ? this.tbar.getHeight() : 0) +
             (this.bbar ? this.bbar.getHeight() : 0);

        if (this.frame) {
            h += this.el.dom.firstChild.offsetHeight + this.ft.dom.offsetHeight + this.mc.getFrameWidth('tb');
        } else {
            h += (this.header ? this.header.getHeight() : 0) +
                (this.footer ? this.footer.getHeight() : 0);
        }
        return h;
    },


    getInnerWidth: function () {
        return this.getSize().width - this.getFrameWidth();
    },


    getInnerHeight: function () {
        return this.body.getHeight();

    },


    syncShadow: function () {
        if (this.floating) {
            this.el.sync(true);
        }
    },


    getLayoutTarget: function () {
        return this.body;
    },


    getContentTarget: function () {
        return this.body;
    },


    setTitle: function (title, iconCls) {
        this.title = title;
        if (this.header && this.headerAsText) {
            this.header.child('span').update(title);
        }
        if (iconCls) {
            this.setIconClass(iconCls);
        }
        this.fireEvent('titlechange', this, title);
        return this;
    },


    getUpdater: function () {
        return this.body.getUpdater();
    },


    load: function () {
        var um = this.body.getUpdater();
        um.update.apply(um, arguments);
        return this;
    },


    beforeDestroy: function () {
        Ext.Panel.superclass.beforeDestroy.call(this);
        if (this.header) {
            this.header.removeAllListeners();
        }
        if (this.tools) {
            for (var k in this.tools) {
                Ext.destroy(this.tools[k]);
            }
        }
        if (this.toolbars.length > 0) {
            Ext.each(this.toolbars, function (tb) {
                tb.un('afterlayout', this.syncHeight, this);
                tb.un('remove', this.syncHeight, this);
            }, this);
        }
        if (Ext.isArray(this.buttons)) {
            while (this.buttons.length) {
                Ext.destroy(this.buttons[0]);
            }
        }
        if (this.rendered) {
            Ext.destroy(
                this.ft,
                this.header,
                this.footer,
                this.tbar,
                this.bbar,
                this.body,
                this.mc,
                this.bwrap,
                this.dd
            );
            if (this.fbar) {
                Ext.destroy(
                    this.fbar,
                    this.fbar.el
                );
            }
        }
        Ext.destroy(this.toolbars);
    },


    createClasses: function () {
        this.headerCls = this.baseCls + '-header';
        this.headerTextCls = this.baseCls + '-header-text';
        this.bwrapCls = this.baseCls + '-bwrap';
        this.tbarCls = this.baseCls + '-tbar';
        this.bodyCls = this.baseCls + '-body';
        this.bbarCls = this.baseCls + '-bbar';
        this.footerCls = this.baseCls + '-footer';
    },


    createGhost: function (cls, useShim, appendTo) {
        var el = document.createElement('div');
        el.className = 'x-panel-ghost ' + (cls ? cls : '');
        if (this.header) {
            el.appendChild(this.el.dom.firstChild.cloneNode(true));
        }
        Ext.fly(el.appendChild(document.createElement('ul'))).setHeight(this.bwrap.getHeight());
        el.style.width = this.el.dom.offsetWidth + 'px'; ;
        if (!appendTo) {
            this.container.dom.appendChild(el);
        } else {
            Ext.getDom(appendTo).appendChild(el);
        }
        if (useShim !== false && this.el.useShim !== false) {
            var layer = new Ext.Layer({ shadow: false, useDisplay: true, constrain: false }, el);
            layer.show();
            return layer;
        } else {
            return new Ext.Element(el);
        }
    },


    doAutoLoad: function () {
        var u = this.body.getUpdater();
        if (this.renderer) {
            u.setRenderer(this.renderer);
        }
        u.update(Ext.isObject(this.autoLoad) ? this.autoLoad : { url: this.autoLoad });
    },


    getTool: function (id) {
        return this.tools[id];
    }


});
Ext.reg('panel', Ext.Panel);

Ext.Editor = function (field, config) {
    if (field.field) {
        this.field = Ext.create(field.field, 'textfield');
        config = Ext.apply({}, field);
        delete config.field;
    } else {
        this.field = field;
    }
    Ext.Editor.superclass.constructor.call(this, config);
};

Ext.extend(Ext.Editor, Ext.Component, {


    allowBlur: true,





    value: "",

    alignment: "c-c?",

    offsets: [0, 0],

    shadow: "frame",

    constrain: false,

    swallowKeys: true,

    completeOnEnter: true,

    cancelOnEsc: true,

    updateEl: false,

    initComponent: function () {
        Ext.Editor.superclass.initComponent.call(this);
        this.addEvents(

            "beforestartedit",

            "startedit",

            "beforecomplete",

            "complete",

            "canceledit",

            "specialkey"
        );
    },


    onRender: function (ct, position) {
        this.el = new Ext.Layer({
            shadow: this.shadow,
            cls: "x-editor",
            parentEl: ct,
            shim: this.shim,
            shadowOffset: this.shadowOffset || 4,
            id: this.id,
            constrain: this.constrain
        });
        if (this.zIndex) {
            this.el.setZIndex(this.zIndex);
        }
        this.el.setStyle("overflow", Ext.isGecko ? "auto" : "hidden");
        if (this.field.msgTarget != 'title') {
            this.field.msgTarget = 'qtip';
        }
        this.field.inEditor = true;
        this.mon(this.field, {
            scope: this,
            blur: this.onBlur,
            specialkey: this.onSpecialKey
        });
        if (this.field.grow) {
            this.mon(this.field, "autosize", this.el.sync, this.el, { delay: 1 });
        }
        this.field.render(this.el).show();
        this.field.getEl().dom.name = '';
        if (this.swallowKeys) {
            this.field.el.swallowEvent([
                'keypress',
                'keydown'
            ]);
        }
    },


    onSpecialKey: function (field, e) {
        var key = e.getKey(),
            complete = this.completeOnEnter && key == e.ENTER,
            cancel = this.cancelOnEsc && key == e.ESC;
        if (complete || cancel) {
            e.stopEvent();
            if (complete) {
                this.completeEdit();
            } else {
                this.cancelEdit();
            }
            if (field.triggerBlur) {
                field.triggerBlur();
            }
        }
        this.fireEvent('specialkey', field, e);
    },


    startEdit: function (el, value) {
        if (this.editing) {
            this.completeEdit();
        }
        this.boundEl = Ext.get(el);
        var v = value !== undefined ? value : this.boundEl.dom.innerHTML;
        if (!this.rendered) {
            this.render(this.parentEl || document.body);
        }
        if (this.fireEvent("beforestartedit", this, this.boundEl, v) !== false) {
            this.startValue = v;
            this.field.reset();
            this.field.setValue(v);
            this.realign(true);
            this.editing = true;
            this.show();
        }
    },


    doAutoSize: function () {
        if (this.autoSize) {
            var sz = this.boundEl.getSize(),
                fs = this.field.getSize();

            switch (this.autoSize) {
                case "width":
                    this.setSize(sz.width, fs.height);
                    break;
                case "height":
                    this.setSize(fs.width, sz.height);
                    break;
                case "none":
                    this.setSize(fs.width, fs.height);
                    break;
                default:
                    this.setSize(sz.width, sz.height);
            }
        }
    },


    setSize: function (w, h) {
        delete this.field.lastSize;
        this.field.setSize(w, h);
        if (this.el) {

            if (Ext.isGecko2 || Ext.isOpera || (Ext.isIE7 && Ext.isStrict)) {

                this.el.setSize(w, h);
            }
            this.el.sync();
        }
    },


    realign: function (autoSize) {
        if (autoSize === true) {
            this.doAutoSize();
        }
        this.el.alignTo(this.boundEl, this.alignment, this.offsets);
    },


    completeEdit: function (remainVisible) {
        if (!this.editing) {
            return;
        }

        if (this.field.assertValue) {
            this.field.assertValue();
        }
        var v = this.getValue();
        if (!this.field.isValid()) {
            if (this.revertInvalid !== false) {
                this.cancelEdit(remainVisible);
            }
            return;
        }
        if (String(v) === String(this.startValue) && this.ignoreNoChange) {
            this.hideEdit(remainVisible);
            return;
        }
        if (this.fireEvent("beforecomplete", this, v, this.startValue) !== false) {
            v = this.getValue();
            if (this.updateEl && this.boundEl) {
                this.boundEl.update(v);
            }
            this.hideEdit(remainVisible);
            this.fireEvent("complete", this, v, this.startValue);
        }
    },


    onShow: function () {
        this.el.show();
        if (this.hideEl !== false) {
            this.boundEl.hide();
        }
        this.field.show().focus(false, true);
        this.fireEvent("startedit", this.boundEl, this.startValue);
    },


    cancelEdit: function (remainVisible) {
        if (this.editing) {
            var v = this.getValue();
            this.setValue(this.startValue);
            this.hideEdit(remainVisible);
            this.fireEvent("canceledit", this, v, this.startValue);
        }
    },


    hideEdit: function (remainVisible) {
        if (remainVisible !== true) {
            this.editing = false;
            this.hide();
        }
    },


    onBlur: function () {

        if (this.allowBlur === true && this.editing && this.selectSameEditor !== true) {
            this.completeEdit();
        }
    },


    onHide: function () {
        if (this.editing) {
            this.completeEdit();
            return;
        }
        this.field.blur();
        if (this.field.collapse) {
            this.field.collapse();
        }
        this.el.hide();
        if (this.hideEl !== false) {
            this.boundEl.show();
        }
    },


    setValue: function (v) {
        this.field.setValue(v);
    },


    getValue: function () {
        return this.field.getValue();
    },

    beforeDestroy: function () {
        Ext.destroyMembers(this, 'field');

        delete this.parentEl;
        delete this.boundEl;
    }
});
Ext.reg('editor', Ext.Editor);

Ext.ColorPalette = Ext.extend(Ext.Component, {


    itemCls: 'x-color-palette',

    value: null,

    clickEvent: 'click',

    ctype: 'Ext.ColorPalette',


    allowReselect: false,


    colors: [
        '000000', '993300', '333300', '003300', '003366', '000080', '333399', '333333',
        '800000', 'FF6600', '808000', '008000', '008080', '0000FF', '666699', '808080',
        'FF0000', 'FF9900', '99CC00', '339966', '33CCCC', '3366FF', '800080', '969696',
        'FF00FF', 'FFCC00', 'FFFF00', '00FF00', '00FFFF', '00CCFF', '993366', 'C0C0C0',
        'FF99CC', 'FFCC99', 'FFFF99', 'CCFFCC', 'CCFFFF', '99CCFF', 'CC99FF', 'FFFFFF'
    ],





    initComponent: function () {
        Ext.ColorPalette.superclass.initComponent.call(this);
        this.addEvents(

            'select'
        );

        if (this.handler) {
            this.on('select', this.handler, this.scope, true);
        }
    },


    onRender: function (container, position) {
        this.autoEl = {
            tag: 'div',
            cls: this.itemCls
        };
        Ext.ColorPalette.superclass.onRender.call(this, container, position);
        var t = this.tpl || new Ext.XTemplate(
            '<tpl for="."><a href="#" class="color-{.}" hidefocus="on"><em><span style="background:#{.}" unselectable="on">&#160;</span></em></a></tpl>'
        );
        t.overwrite(this.el, this.colors);
        this.mon(this.el, this.clickEvent, this.handleClick, this, { delegate: 'a' });
        if (this.clickEvent != 'click') {
            this.mon(this.el, 'click', Ext.emptyFn, this, { delegate: 'a', preventDefault: true });
        }
    },


    afterRender: function () {
        Ext.ColorPalette.superclass.afterRender.call(this);
        if (this.value) {
            var s = this.value;
            this.value = null;
            this.select(s, true);
        }
    },


    handleClick: function (e, t) {
        e.preventDefault();
        if (!this.disabled) {
            var c = t.className.match(/(?:^|\s)color-(.{6})(?:\s|$)/)[1];
            this.select(c.toUpperCase());
        }
    },


    select: function (color, suppressEvent) {
        color = color.replace('#', '');
        if (color != this.value || this.allowReselect) {
            var el = this.el;
            if (this.value) {
                el.child('a.color-' + this.value).removeClass('x-color-palette-sel');
            }
            el.child('a.color-' + color).addClass('x-color-palette-sel');
            this.value = color;
            if (suppressEvent !== true) {
                this.fireEvent('select', this, color);
            }
        }
    }


});
Ext.reg('colorpalette', Ext.ColorPalette);
Ext.DatePicker = Ext.extend(Ext.BoxComponent, {

    todayText: 'Today',

    okText: '&#160;OK&#160;',

    cancelText: 'Cancel',



    todayTip: '{0} (Spacebar)',

    minText: 'This date is before the minimum date',

    maxText: 'This date is after the maximum date',

    format: 'm/d/y',

    disabledDaysText: 'Disabled',

    disabledDatesText: 'Disabled',

    monthNames: Date.monthNames,

    dayNames: Date.dayNames,

    nextText: 'Next Month (Control+Right)',

    prevText: 'Previous Month (Control+Left)',

    monthYearText: 'Choose a month (Control+Up/Down to move years)',

    startDay: 0,

    showToday: true,








    focusOnSelect: true,



    initHour: 12,


    initComponent: function () {
        Ext.DatePicker.superclass.initComponent.call(this);

        this.value = this.value ?
                 this.value.clearTime(true) : new Date().clearTime();

        this.addEvents(

            'select'
        );

        if (this.handler) {
            this.on('select', this.handler, this.scope || this);
        }

        this.initDisabledDays();
    },


    initDisabledDays: function () {
        if (!this.disabledDatesRE && this.disabledDates) {
            var dd = this.disabledDates,
                len = dd.length - 1,
                re = '(?:';

            Ext.each(dd, function (d, i) {
                re += Ext.isDate(d) ? '^' + Ext.escapeRe(d.dateFormat(this.format)) + '$' : dd[i];
                if (i != len) {
                    re += '|';
                }
            }, this);
            this.disabledDatesRE = new RegExp(re + ')');
        }
    },


    setDisabledDates: function (dd) {
        if (Ext.isArray(dd)) {
            this.disabledDates = dd;
            this.disabledDatesRE = null;
        } else {
            this.disabledDatesRE = dd;
        }
        this.initDisabledDays();
        this.update(this.value, true);
    },


    setDisabledDays: function (dd) {
        this.disabledDays = dd;
        this.update(this.value, true);
    },


    setMinDate: function (dt) {
        this.minDate = dt;
        this.update(this.value, true);
    },


    setMaxDate: function (dt) {
        this.maxDate = dt;
        this.update(this.value, true);
    },


    setValue: function (value) {
        this.value = value.clearTime(true);
        this.update(this.value);
    },


    getValue: function () {
        return this.value;
    },


    focus: function () {
        this.update(this.activeDate);
    },


    onEnable: function (initial) {
        Ext.DatePicker.superclass.onEnable.call(this);
        this.doDisabled(false);
        this.update(initial ? this.value : this.activeDate);
        if (Ext.isIE) {
            this.el.repaint();
        }

    },


    onDisable: function () {
        Ext.DatePicker.superclass.onDisable.call(this);
        this.doDisabled(true);
        if (Ext.isIE && !Ext.isIE8) {

            Ext.each([].concat(this.textNodes, this.el.query('th span')), function (el) {
                Ext.fly(el).repaint();
            });
        }
    },


    doDisabled: function (disabled) {
        this.keyNav.setDisabled(disabled);
        this.prevRepeater.setDisabled(disabled);
        this.nextRepeater.setDisabled(disabled);
        if (this.showToday) {
            this.todayKeyListener.setDisabled(disabled);
            this.todayBtn.setDisabled(disabled);
        }
    },


    onRender: function (container, position) {
        var m = [
             '<table cellspacing="0">',
                '<tr><td class="x-date-left"><a href="#" title="', this.prevText, '">&#160;</a></td><td class="x-date-middle" align="center"></td><td class="x-date-right"><a href="#" title="', this.nextText, '">&#160;</a></td></tr>',
                '<tr><td colspan="3"><table class="x-date-inner" cellspacing="0"><thead><tr>'],
                dn = this.dayNames,
                i;
        for (i = 0; i < 7; i++) {
            var d = this.startDay + i;
            if (d > 6) {
                d = d - 7;
            }
            m.push('<th><span>', dn[d].substr(0, 1), '</span></th>');
        }
        m[m.length] = '</tr></thead><tbody><tr>';
        for (i = 0; i < 42; i++) {
            if (i % 7 === 0 && i !== 0) {
                m[m.length] = '</tr><tr>';
            }
            m[m.length] = '<td><a href="#" hidefocus="on" class="x-date-date" tabIndex="1"><em><span></span></em></a></td>';
        }
        m.push('</tr></tbody></table></td></tr>',
                this.showToday ? '<tr><td colspan="3" class="x-date-bottom" align="center"></td></tr>' : '',
                '</table><div class="x-date-mp"></div>');

        var el = document.createElement('div');
        el.className = 'x-date-picker';
        el.innerHTML = m.join('');

        container.dom.insertBefore(el, position);

        this.el = Ext.get(el);
        this.eventEl = Ext.get(el.firstChild);

        this.prevRepeater = new Ext.util.ClickRepeater(this.el.child('td.x-date-left a'), {
            handler: this.showPrevMonth,
            scope: this,
            preventDefault: true,
            stopDefault: true
        });

        this.nextRepeater = new Ext.util.ClickRepeater(this.el.child('td.x-date-right a'), {
            handler: this.showNextMonth,
            scope: this,
            preventDefault: true,
            stopDefault: true
        });

        this.monthPicker = this.el.down('div.x-date-mp');
        this.monthPicker.enableDisplayMode('block');

        this.keyNav = new Ext.KeyNav(this.eventEl, {
            'left': function (e) {
                if (e.ctrlKey) {
                    this.showPrevMonth();
                } else {
                    this.update(this.activeDate.add('d', -1));
                }
            },

            'right': function (e) {
                if (e.ctrlKey) {
                    this.showNextMonth();
                } else {
                    this.update(this.activeDate.add('d', 1));
                }
            },

            'up': function (e) {
                if (e.ctrlKey) {
                    this.showNextYear();
                } else {
                    this.update(this.activeDate.add('d', -7));
                }
            },

            'down': function (e) {
                if (e.ctrlKey) {
                    this.showPrevYear();
                } else {
                    this.update(this.activeDate.add('d', 7));
                }
            },

            'pageUp': function (e) {
                this.showNextMonth();
            },

            'pageDown': function (e) {
                this.showPrevMonth();
            },

            'enter': function (e) {
                e.stopPropagation();
                return true;
            },

            scope: this
        });

        this.el.unselectable();

        this.cells = this.el.select('table.x-date-inner tbody td');
        this.textNodes = this.el.query('table.x-date-inner tbody span');

        this.mbtn = new Ext.Button({
            text: '&#160;',
            tooltip: this.monthYearText,
            renderTo: this.el.child('td.x-date-middle', true)
        });
        this.mbtn.el.child('em').addClass('x-btn-arrow');

        if (this.showToday) {
            this.todayKeyListener = this.eventEl.addKeyListener(Ext.EventObject.SPACE, this.selectToday, this);
            var today = (new Date()).dateFormat(this.format);
            this.todayBtn = new Ext.Button({
                renderTo: this.el.child('td.x-date-bottom', true),
                text: String.format(this.todayText, today),
                tooltip: String.format(this.todayTip, today),
                handler: this.selectToday,
                scope: this
            });
        }
        this.mon(this.eventEl, 'mousewheel', this.handleMouseWheel, this);
        this.mon(this.eventEl, 'click', this.handleDateClick, this, { delegate: 'a.x-date-date' });
        this.mon(this.mbtn, 'click', this.showMonthPicker, this);
        this.onEnable(true);
    },


    createMonthPicker: function () {
        if (!this.monthPicker.dom.firstChild) {
            var buf = ['<table border="0" cellspacing="0">'];
            for (var i = 0; i < 6; i++) {
                buf.push(
                    '<tr><td class="x-date-mp-month"><a href="#">', Date.getShortMonthName(i), '</a></td>',
                    '<td class="x-date-mp-month x-date-mp-sep"><a href="#">', Date.getShortMonthName(i + 6), '</a></td>',
                    i === 0 ?
                    '<td class="x-date-mp-ybtn" align="center"><a class="x-date-mp-prev"></a></td><td class="x-date-mp-ybtn" align="center"><a class="x-date-mp-next"></a></td></tr>' :
                    '<td class="x-date-mp-year"><a href="#"></a></td><td class="x-date-mp-year"><a href="#"></a></td></tr>'
                );
            }
            buf.push(
                '<tr class="x-date-mp-btns"><td colspan="4"><button type="button" class="x-date-mp-ok">',
                    this.okText,
                    '</button><button type="button" class="x-date-mp-cancel">',
                    this.cancelText,
                    '</button></td></tr>',
                '</table>'
            );
            this.monthPicker.update(buf.join(''));

            this.mon(this.monthPicker, 'click', this.onMonthClick, this);
            this.mon(this.monthPicker, 'dblclick', this.onMonthDblClick, this);

            this.mpMonths = this.monthPicker.select('td.x-date-mp-month');
            this.mpYears = this.monthPicker.select('td.x-date-mp-year');

            this.mpMonths.each(function (m, a, i) {
                i += 1;
                if ((i % 2) === 0) {
                    m.dom.xmonth = 5 + Math.round(i * 0.5);
                } else {
                    m.dom.xmonth = Math.round((i - 1) * 0.5);
                }
            });
        }
    },


    showMonthPicker: function () {
        if (!this.disabled) {
            this.createMonthPicker();
            var size = this.el.getSize();
            this.monthPicker.setSize(size);
            this.monthPicker.child('table').setSize(size);

            this.mpSelMonth = (this.activeDate || this.value).getMonth();
            this.updateMPMonth(this.mpSelMonth);
            this.mpSelYear = (this.activeDate || this.value).getFullYear();
            this.updateMPYear(this.mpSelYear);

            this.monthPicker.slideIn('t', { duration: 0.2 });
        }
    },


    updateMPYear: function (y) {
        this.mpyear = y;
        var ys = this.mpYears.elements;
        for (var i = 1; i <= 10; i++) {
            var td = ys[i - 1], y2;
            if ((i % 2) === 0) {
                y2 = y + Math.round(i * 0.5);
                td.firstChild.innerHTML = y2;
                td.xyear = y2;
            } else {
                y2 = y - (5 - Math.round(i * 0.5));
                td.firstChild.innerHTML = y2;
                td.xyear = y2;
            }
            this.mpYears.item(i - 1)[y2 == this.mpSelYear ? 'addClass' : 'removeClass']('x-date-mp-sel');
        }
    },


    updateMPMonth: function (sm) {
        this.mpMonths.each(function (m, a, i) {
            m[m.dom.xmonth == sm ? 'addClass' : 'removeClass']('x-date-mp-sel');
        });
    },


    selectMPMonth: function (m) {

    },


    onMonthClick: function (e, t) {
        e.stopEvent();
        var el = new Ext.Element(t), pn;
        if (el.is('button.x-date-mp-cancel')) {
            this.hideMonthPicker();
        }
        else if (el.is('button.x-date-mp-ok')) {
            var d = new Date(this.mpSelYear, this.mpSelMonth, (this.activeDate || this.value).getDate());
            if (d.getMonth() != this.mpSelMonth) {

                d = new Date(this.mpSelYear, this.mpSelMonth, 1).getLastDateOfMonth();
            }
            this.update(d);
            this.hideMonthPicker();
        }
        else if ((pn = el.up('td.x-date-mp-month', 2))) {
            this.mpMonths.removeClass('x-date-mp-sel');
            pn.addClass('x-date-mp-sel');
            this.mpSelMonth = pn.dom.xmonth;
        }
        else if ((pn = el.up('td.x-date-mp-year', 2))) {
            this.mpYears.removeClass('x-date-mp-sel');
            pn.addClass('x-date-mp-sel');
            this.mpSelYear = pn.dom.xyear;
        }
        else if (el.is('a.x-date-mp-prev')) {
            this.updateMPYear(this.mpyear - 10);
        }
        else if (el.is('a.x-date-mp-next')) {
            this.updateMPYear(this.mpyear + 10);
        }
    },


    onMonthDblClick: function (e, t) {
        e.stopEvent();
        var el = new Ext.Element(t), pn;
        if ((pn = el.up('td.x-date-mp-month', 2))) {
            this.update(new Date(this.mpSelYear, pn.dom.xmonth, (this.activeDate || this.value).getDate()));
            this.hideMonthPicker();
        }
        else if ((pn = el.up('td.x-date-mp-year', 2))) {
            this.update(new Date(pn.dom.xyear, this.mpSelMonth, (this.activeDate || this.value).getDate()));
            this.hideMonthPicker();
        }
    },


    hideMonthPicker: function (disableAnim) {
        if (this.monthPicker) {
            if (disableAnim === true) {
                this.monthPicker.hide();
            } else {
                this.monthPicker.slideOut('t', { duration: 0.2 });
            }
        }
    },


    showPrevMonth: function (e) {
        this.update(this.activeDate.add('mo', -1));
    },


    showNextMonth: function (e) {
        this.update(this.activeDate.add('mo', 1));
    },


    showPrevYear: function () {
        this.update(this.activeDate.add('y', -1));
    },


    showNextYear: function () {
        this.update(this.activeDate.add('y', 1));
    },


    handleMouseWheel: function (e) {
        e.stopEvent();
        if (!this.disabled) {
            var delta = e.getWheelDelta();
            if (delta > 0) {
                this.showPrevMonth();
            } else if (delta < 0) {
                this.showNextMonth();
            }
        }
    },


    handleDateClick: function (e, t) {
        e.stopEvent();
        if (!this.disabled && t.dateValue && !Ext.fly(t.parentNode).hasClass('x-date-disabled')) {
            this.cancelFocus = this.focusOnSelect === false;
            this.setValue(new Date(t.dateValue));
            delete this.cancelFocus;
            this.fireEvent('select', this, this.value);
        }
    },


    selectToday: function () {
        if (this.todayBtn && !this.todayBtn.disabled) {
            this.setValue(new Date().clearTime());
            this.fireEvent('select', this, this.value);
        }
    },


    update: function (date, forceRefresh) {
        if (this.rendered) {
            var vd = this.activeDate, vis = this.isVisible();
            this.activeDate = date;
            if (!forceRefresh && vd && this.el) {
                var t = date.getTime();
                if (vd.getMonth() == date.getMonth() && vd.getFullYear() == date.getFullYear()) {
                    this.cells.removeClass('x-date-selected');
                    this.cells.each(function (c) {
                        if (c.dom.firstChild.dateValue == t) {
                            c.addClass('x-date-selected');
                            if (vis && !this.cancelFocus) {
                                Ext.fly(c.dom.firstChild).focus(50);
                            }
                            return false;
                        }
                    }, this);
                    return;
                }
            }
            var days = date.getDaysInMonth(),
                firstOfMonth = date.getFirstDateOfMonth(),
                startingPos = firstOfMonth.getDay() - this.startDay;

            if (startingPos < 0) {
                startingPos += 7;
            }
            days += startingPos;

            var pm = date.add('mo', -1),
                prevStart = pm.getDaysInMonth() - startingPos,
                cells = this.cells.elements,
                textEls = this.textNodes,

                d = (new Date(pm.getFullYear(), pm.getMonth(), prevStart, this.initHour)),
                today = new Date().clearTime().getTime(),
                sel = date.clearTime(true).getTime(),
                min = this.minDate ? this.minDate.clearTime(true) : Number.NEGATIVE_INFINITY,
                max = this.maxDate ? this.maxDate.clearTime(true) : Number.POSITIVE_INFINITY,
                ddMatch = this.disabledDatesRE,
                ddText = this.disabledDatesText,
                ddays = this.disabledDays ? this.disabledDays.join('') : false,
                ddaysText = this.disabledDaysText,
                format = this.format;

            if (this.showToday) {
                var td = new Date().clearTime(),
                    disable = (td < min || td > max ||
                    (ddMatch && format && ddMatch.test(td.dateFormat(format))) ||
                    (ddays && ddays.indexOf(td.getDay()) != -1));

                if (!this.disabled) {
                    this.todayBtn.setDisabled(disable);
                    this.todayKeyListener[disable ? 'disable' : 'enable']();
                }
            }

            var setCellClass = function (cal, cell) {
                cell.title = '';
                var t = d.clearTime(true).getTime();
                cell.firstChild.dateValue = t;
                if (t == today) {
                    cell.className += ' x-date-today';
                    cell.title = cal.todayText;
                }
                if (t == sel) {
                    cell.className += ' x-date-selected';
                    if (vis) {
                        Ext.fly(cell.firstChild).focus(50);
                    }
                }

                if (t < min) {
                    cell.className = ' x-date-disabled';
                    cell.title = cal.minText;
                    return;
                }
                if (t > max) {
                    cell.className = ' x-date-disabled';
                    cell.title = cal.maxText;
                    return;
                }
                if (ddays) {
                    if (ddays.indexOf(d.getDay()) != -1) {
                        cell.title = ddaysText;
                        cell.className = ' x-date-disabled';
                    }
                }
                if (ddMatch && format) {
                    var fvalue = d.dateFormat(format);
                    if (ddMatch.test(fvalue)) {
                        cell.title = ddText.replace('%0', fvalue);
                        cell.className = ' x-date-disabled';
                    }
                }
            };

            var i = 0;
            for (; i < startingPos; i++) {
                textEls[i].innerHTML = (++prevStart);
                d.setDate(d.getDate() + 1);
                cells[i].className = 'x-date-prevday';
                setCellClass(this, cells[i]);
            }
            for (; i < days; i++) {
                var intDay = i - startingPos + 1;
                textEls[i].innerHTML = (intDay);
                d.setDate(d.getDate() + 1);
                cells[i].className = 'x-date-active';
                setCellClass(this, cells[i]);
            }
            var extraDays = 0;
            for (; i < 42; i++) {
                textEls[i].innerHTML = (++extraDays);
                d.setDate(d.getDate() + 1);
                cells[i].className = 'x-date-nextday';
                setCellClass(this, cells[i]);
            }

            this.mbtn.setText(this.monthNames[date.getMonth()] + ' ' + date.getFullYear());

            if (!this.internalRender) {
                var main = this.el.dom.firstChild,
                    w = main.offsetWidth;
                this.el.setWidth(w + this.el.getBorderWidth('lr'));
                Ext.fly(main).setWidth(w);
                this.internalRender = true;



                if (Ext.isOpera && !this.secondPass) {
                    main.rows[0].cells[1].style.width = (w - (main.rows[0].cells[0].offsetWidth + main.rows[0].cells[2].offsetWidth)) + 'px';
                    this.secondPass = true;
                    this.update.defer(10, this, [date]);
                }
            }
        }
    },


    beforeDestroy: function () {
        if (this.rendered) {
            Ext.destroy(
                this.keyNav,
                this.monthPicker,
                this.eventEl,
                this.mbtn,
                this.nextRepeater,
                this.prevRepeater,
                this.cells.el,
                this.todayBtn
            );
            delete this.textNodes;
            delete this.cells.elements;
        }
    }


});

Ext.reg('datepicker', Ext.DatePicker);

Ext.LoadMask = function (el, config) {
    this.el = Ext.get(el);
    Ext.apply(this, config);
    if (this.store) {
        this.store.on({
            scope: this,
            beforeload: this.onBeforeLoad,
            load: this.onLoad,
            exception: this.onLoad
        });
        this.removeMask = Ext.value(this.removeMask, false);
    } else {
        var um = this.el.getUpdater();
        um.showLoadIndicator = false;
        um.on({
            scope: this,
            beforeupdate: this.onBeforeLoad,
            update: this.onLoad,
            failure: this.onLoad
        });
        this.removeMask = Ext.value(this.removeMask, true);
    }
};

Ext.LoadMask.prototype = {



    msg: 'Loading...',

    msgCls: 'x-mask-loading',


    disabled: false,


    disable: function () {
        this.disabled = true;
    },


    enable: function () {
        this.disabled = false;
    },


    onLoad: function () {
        this.el.unmask(this.removeMask);
    },


    onBeforeLoad: function () {
        if (!this.disabled) {
            this.el.mask(this.msg, this.msgCls);
        }
    },


    show: function () {
        this.onBeforeLoad();
    },


    hide: function () {
        this.onLoad();
    },


    destroy: function () {
        if (this.store) {
            this.store.un('beforeload', this.onBeforeLoad, this);
            this.store.un('load', this.onLoad, this);
            this.store.un('exception', this.onLoad, this);
        } else {
            var um = this.el.getUpdater();
            um.un('beforeupdate', this.onBeforeLoad, this);
            um.un('update', this.onLoad, this);
            um.un('failure', this.onLoad, this);
        }
    }
}; Ext.ns('Ext.slider');


Ext.slider.Thumb = Ext.extend(Object, {


    dragging: false,


    constructor: function (config) {

        Ext.apply(this, config || {}, {
            cls: 'x-slider-thumb',


            constrain: false
        });

        Ext.slider.Thumb.superclass.constructor.call(this, config);

        if (this.slider.vertical) {
            Ext.apply(this, Ext.slider.Thumb.Vertical);
        }
    },


    render: function () {
        this.el = this.slider.innerEl.insertFirst({ cls: this.cls });

        this.initEvents();
    },


    enable: function () {
        this.disabled = false;
        this.el.removeClass(this.slider.disabledClass);
    },


    disable: function () {
        this.disabled = true;
        this.el.addClass(this.slider.disabledClass);
    },


    initEvents: function () {
        var el = this.el;

        el.addClassOnOver('x-slider-thumb-over');

        this.tracker = new Ext.dd.DragTracker({
            onBeforeStart: this.onBeforeDragStart.createDelegate(this),
            onStart: this.onDragStart.createDelegate(this),
            onDrag: this.onDrag.createDelegate(this),
            onEnd: this.onDragEnd.createDelegate(this),
            tolerance: 3,
            autoStart: 300
        });

        this.tracker.initEl(el);
    },


    onBeforeDragStart: function (e) {
        if (this.disabled) {
            return false;
        } else {
            this.slider.promoteThumb(this);
            return true;
        }
    },


    onDragStart: function (e) {
        this.el.addClass('x-slider-thumb-drag');
        this.dragging = true;
        this.dragStartValue = this.value;

        this.slider.fireEvent('dragstart', this.slider, e, this);
    },


    onDrag: function (e) {
        var slider = this.slider,
            index = this.index,
            newValue = this.getNewValue();

        if (this.constrain) {
            var above = slider.thumbs[index + 1],
                below = slider.thumbs[index - 1];

            if (below != undefined && newValue <= below.value) newValue = below.value;
            if (above != undefined && newValue >= above.value) newValue = above.value;
        }

        slider.setValue(index, newValue, false);
        slider.fireEvent('drag', slider, e, this);
    },

    getNewValue: function () {
        var slider = this.slider,
            pos = slider.innerEl.translatePoints(this.tracker.getXY());

        return Ext.util.Format.round(slider.reverseValue(pos.left), slider.decimalPrecision);
    },


    onDragEnd: function (e) {
        var slider = this.slider,
            value = this.value;

        this.el.removeClass('x-slider-thumb-drag');

        this.dragging = false;
        slider.fireEvent('dragend', slider, e);

        if (this.dragStartValue != value) {
            slider.fireEvent('changecomplete', slider, value, this);
        }
    },


    destroy: function () {
        Ext.destroyMembers(this, 'tracker', 'el');
    }
});


Ext.slider.MultiSlider = Ext.extend(Ext.BoxComponent, {


    vertical: false,

    minValue: 0,

    maxValue: 100,

    decimalPrecision: 0,

    keyIncrement: 1,

    increment: 0,


    clickRange: [5, 15],


    clickToChange: true,

    animate: true,

    constrainThumbs: true,


    topThumbZIndex: 10000,


    initComponent: function () {
        if (!Ext.isDefined(this.value)) {
            this.value = this.minValue;
        }


        this.thumbs = [];

        Ext.slider.MultiSlider.superclass.initComponent.call(this);

        this.keyIncrement = Math.max(this.increment, this.keyIncrement);
        this.addEvents(

            'beforechange',


            'change',


            'changecomplete',


            'dragstart',


            'drag',


            'dragend'
        );


        if (this.values == undefined || Ext.isEmpty(this.values)) this.values = [0];

        var values = this.values;

        for (var i = 0; i < values.length; i++) {
            this.addThumb(values[i]);
        }

        if (this.vertical) {
            Ext.apply(this, Ext.slider.Vertical);
        }
    },


    addThumb: function (value) {
        var thumb = new Ext.slider.Thumb({
            value: value,
            slider: this,
            index: this.thumbs.length,
            constrain: this.constrainThumbs
        });
        this.thumbs.push(thumb);


        if (this.rendered) thumb.render();
    },


    promoteThumb: function (topThumb) {
        var thumbs = this.thumbs,
            zIndex, thumb;

        for (var i = 0, j = thumbs.length; i < j; i++) {
            thumb = thumbs[i];

            if (thumb == topThumb) {
                zIndex = this.topThumbZIndex;
            } else {
                zIndex = '';
            }

            thumb.el.setStyle('zIndex', zIndex);
        }
    },


    onRender: function () {
        this.autoEl = {
            cls: 'x-slider ' + (this.vertical ? 'x-slider-vert' : 'x-slider-horz'),
            cn: {
                cls: 'x-slider-end',
                cn: {
                    cls: 'x-slider-inner',
                    cn: [{ tag: 'a', cls: 'x-slider-focus', href: "#", tabIndex: '-1', hidefocus: 'on'}]
                }
            }
        };

        Ext.slider.MultiSlider.superclass.onRender.apply(this, arguments);

        this.endEl = this.el.first();
        this.innerEl = this.endEl.first();
        this.focusEl = this.innerEl.child('.x-slider-focus');


        for (var i = 0; i < this.thumbs.length; i++) {
            this.thumbs[i].render();
        }


        var thumb = this.innerEl.child('.x-slider-thumb');
        this.halfThumb = (this.vertical ? thumb.getHeight() : thumb.getWidth()) / 2;

        this.initEvents();
    },


    initEvents: function () {
        this.mon(this.el, {
            scope: this,
            mousedown: this.onMouseDown,
            keydown: this.onKeyDown
        });

        this.focusEl.swallowEvent("click", true);
    },


    onMouseDown: function (e) {
        if (this.disabled) {
            return;
        }


        var thumbClicked = false;
        for (var i = 0; i < this.thumbs.length; i++) {
            thumbClicked = thumbClicked || e.target == this.thumbs[i].el.dom;
        }

        if (this.clickToChange && !thumbClicked) {
            var local = this.innerEl.translatePoints(e.getXY());
            this.onClickChange(local);
        }
        this.focus();
    },


    onClickChange: function (local) {
        if (local.top > this.clickRange[0] && local.top < this.clickRange[1]) {

            var thumb = this.getNearest(local, 'left'),
                index = thumb.index;

            this.setValue(index, Ext.util.Format.round(this.reverseValue(local.left), this.decimalPrecision), undefined, true);
        }
    },


    getNearest: function (local, prop) {
        var localValue = prop == 'top' ? this.innerEl.getHeight() - local[prop] : local[prop],
            clickValue = this.reverseValue(localValue),
            nearestDistance = (this.maxValue - this.minValue) + 5,
            index = 0,
            nearest = null;

        for (var i = 0; i < this.thumbs.length; i++) {
            var thumb = this.thumbs[i],
                value = thumb.value,
                dist = Math.abs(value - clickValue);

            if (Math.abs(dist <= nearestDistance)) {
                nearest = thumb;
                index = i;
                nearestDistance = dist;
            }
        }
        return nearest;
    },


    onKeyDown: function (e) {

        if (this.disabled || this.thumbs.length !== 1) {
            e.preventDefault();
            return;
        }
        var k = e.getKey(),
            val;
        switch (k) {
            case e.UP:
            case e.RIGHT:
                e.stopEvent();
                val = e.ctrlKey ? this.maxValue : this.getValue(0) + this.keyIncrement;
                this.setValue(0, val, undefined, true);
                break;
            case e.DOWN:
            case e.LEFT:
                e.stopEvent();
                val = e.ctrlKey ? this.minValue : this.getValue(0) - this.keyIncrement;
                this.setValue(0, val, undefined, true);
                break;
            default:
                e.preventDefault();
        }
    },


    doSnap: function (value) {
        if (!(this.increment && value)) {
            return value;
        }
        var newValue = value,
            inc = this.increment,
            m = value % inc;
        if (m != 0) {
            newValue -= m;
            if (m * 2 >= inc) {
                newValue += inc;
            } else if (m * 2 < -inc) {
                newValue -= inc;
            }
        }
        return newValue.constrain(this.minValue, this.maxValue);
    },


    afterRender: function () {
        Ext.slider.MultiSlider.superclass.afterRender.apply(this, arguments);

        for (var i = 0; i < this.thumbs.length; i++) {
            var thumb = this.thumbs[i];

            if (thumb.value !== undefined) {
                var v = this.normalizeValue(thumb.value);

                if (v !== thumb.value) {

                    this.setValue(i, v, false);
                } else {
                    this.moveThumb(i, this.translateValue(v), false);
                }
            }
        };
    },


    getRatio: function () {
        var w = this.innerEl.getWidth(),
            v = this.maxValue - this.minValue;
        return v == 0 ? w : (w / v);
    },


    normalizeValue: function (v) {
        v = this.doSnap(v);
        v = Ext.util.Format.round(v, this.decimalPrecision);
        v = v.constrain(this.minValue, this.maxValue);
        return v;
    },


    setMinValue: function (val) {
        this.minValue = val;
        var i = 0,
            thumbs = this.thumbs,
            len = thumbs.length,
            t;

        for (; i < len; ++i) {
            t = thumbs[i];
            t.value = t.value < val ? val : t.value;
        }
        this.syncThumb();
    },


    setMaxValue: function (val) {
        this.maxValue = val;
        var i = 0,
            thumbs = this.thumbs,
            len = thumbs.length,
            t;

        for (; i < len; ++i) {
            t = thumbs[i];
            t.value = t.value > val ? val : t.value;
        }
        this.syncThumb();
    },


    setValue: function (index, v, animate, changeComplete) {
        var thumb = this.thumbs[index],
            el = thumb.el;

        v = this.normalizeValue(v);

        if (v !== thumb.value && this.fireEvent('beforechange', this, v, thumb.value, thumb) !== false) {
            thumb.value = v;
            if (this.rendered) {
                this.moveThumb(index, this.translateValue(v), animate !== false);
                this.fireEvent('change', this, v, thumb);
                if (changeComplete) {
                    this.fireEvent('changecomplete', this, v, thumb);
                }
            }
        }
    },


    translateValue: function (v) {
        var ratio = this.getRatio();
        return (v * ratio) - (this.minValue * ratio) - this.halfThumb;
    },


    reverseValue: function (pos) {
        var ratio = this.getRatio();
        return (pos + (this.minValue * ratio)) / ratio;
    },


    moveThumb: function (index, v, animate) {
        var thumb = this.thumbs[index].el;

        if (!animate || this.animate === false) {
            thumb.setLeft(v);
        } else {
            thumb.shift({ left: v, stopFx: true, duration: .35 });
        }
    },


    focus: function () {
        this.focusEl.focus(10);
    },


    onResize: function (w, h) {
        var thumbs = this.thumbs,
            len = thumbs.length,
            i = 0;


        for (; i < len; ++i) {
            thumbs[i].el.stopFx();
        }

        if (Ext.isNumber(w)) {
            this.innerEl.setWidth(w - (this.el.getPadding('l') + this.endEl.getPadding('r')));
        }
        this.syncThumb();
        Ext.slider.MultiSlider.superclass.onResize.apply(this, arguments);
    },


    onDisable: function () {
        Ext.slider.MultiSlider.superclass.onDisable.call(this);

        for (var i = 0; i < this.thumbs.length; i++) {
            var thumb = this.thumbs[i],
                el = thumb.el;

            thumb.disable();

            if (Ext.isIE) {


                var xy = el.getXY();
                el.hide();

                this.innerEl.addClass(this.disabledClass).dom.disabled = true;

                if (!this.thumbHolder) {
                    this.thumbHolder = this.endEl.createChild({ cls: 'x-slider-thumb ' + this.disabledClass });
                }

                this.thumbHolder.show().setXY(xy);
            }
        }
    },


    onEnable: function () {
        Ext.slider.MultiSlider.superclass.onEnable.call(this);

        for (var i = 0; i < this.thumbs.length; i++) {
            var thumb = this.thumbs[i],
                el = thumb.el;

            thumb.enable();

            if (Ext.isIE) {
                this.innerEl.removeClass(this.disabledClass).dom.disabled = false;

                if (this.thumbHolder) this.thumbHolder.hide();

                el.show();
                this.syncThumb();
            }
        }
    },


    syncThumb: function () {
        if (this.rendered) {
            for (var i = 0; i < this.thumbs.length; i++) {
                this.moveThumb(i, this.translateValue(this.thumbs[i].value));
            }
        }
    },


    getValue: function (index) {
        return this.thumbs[index].value;
    },


    getValues: function () {
        var values = [];

        for (var i = 0; i < this.thumbs.length; i++) {
            values.push(this.thumbs[i].value);
        }

        return values;
    },


    beforeDestroy: function () {
        var thumbs = this.thumbs;
        for (var i = 0, len = thumbs.length; i < len; ++i) {
            thumbs[i].destroy();
            thumbs[i] = null;
        }
        Ext.destroyMembers(this, 'endEl', 'innerEl', 'focusEl', 'thumbHolder');
        Ext.slider.MultiSlider.superclass.beforeDestroy.call(this);
    }
});

Ext.reg('multislider', Ext.slider.MultiSlider);


Ext.slider.SingleSlider = Ext.extend(Ext.slider.MultiSlider, {
    constructor: function (config) {
        config = config || {};

        Ext.applyIf(config, {
            values: [config.value || 0]
        });

        Ext.slider.SingleSlider.superclass.constructor.call(this, config);
    },


    getValue: function () {

        return Ext.slider.SingleSlider.superclass.getValue.call(this, 0);
    },


    setValue: function (value, animate) {
        var args = Ext.toArray(arguments),
            len = args.length;




        if (len == 1 || (len <= 3 && typeof arguments[1] != 'number')) {
            args.unshift(0);
        }

        return Ext.slider.SingleSlider.superclass.setValue.apply(this, args);
    },


    syncThumb: function () {
        return Ext.slider.SingleSlider.superclass.syncThumb.apply(this, [0].concat(arguments));
    },


    getNearest: function () {

        return this.thumbs[0];
    }
});


Ext.Slider = Ext.slider.SingleSlider;

Ext.reg('slider', Ext.slider.SingleSlider);


Ext.slider.Vertical = {
    onResize: function (w, h) {
        this.innerEl.setHeight(h - (this.el.getPadding('t') + this.endEl.getPadding('b')));
        this.syncThumb();
    },

    getRatio: function () {
        var h = this.innerEl.getHeight(),
            v = this.maxValue - this.minValue;
        return h / v;
    },

    moveThumb: function (index, v, animate) {
        var thumb = this.thumbs[index],
            el = thumb.el;

        if (!animate || this.animate === false) {
            el.setBottom(v);
        } else {
            el.shift({ bottom: v, stopFx: true, duration: .35 });
        }
    },

    onClickChange: function (local) {
        if (local.left > this.clickRange[0] && local.left < this.clickRange[1]) {
            var thumb = this.getNearest(local, 'top'),
                index = thumb.index,
                value = this.minValue + this.reverseValue(this.innerEl.getHeight() - local.top);

            this.setValue(index, Ext.util.Format.round(value, this.decimalPrecision), undefined, true);
        }
    }
};


Ext.slider.Thumb.Vertical = {
    getNewValue: function () {
        var slider = this.slider,
            innerEl = slider.innerEl,
            pos = innerEl.translatePoints(this.tracker.getXY()),
            bottom = innerEl.getHeight() - pos.top;

        return slider.minValue + Ext.util.Format.round(bottom / slider.getRatio(), slider.decimalPrecision);
    }
};

Ext.ProgressBar = Ext.extend(Ext.BoxComponent, {

    baseCls: 'x-progress',


    animate: false,


    waitTimer: null,


    initComponent: function () {
        Ext.ProgressBar.superclass.initComponent.call(this);
        this.addEvents(

            "update"
        );
    },


    onRender: function (ct, position) {
        var tpl = new Ext.Template(
            '<div class="{cls}-wrap">',
                '<div class="{cls}-inner">',
                    '<div class="{cls}-bar">',
                        '<div class="{cls}-text">',
                            '<div>&#160;</div>',
                        '</div>',
                    '</div>',
                    '<div class="{cls}-text {cls}-text-back">',
                        '<div>&#160;</div>',
                    '</div>',
                '</div>',
            '</div>'
        );

        this.el = position ? tpl.insertBefore(position, { cls: this.baseCls }, true)
            : tpl.append(ct, { cls: this.baseCls }, true);

        if (this.id) {
            this.el.dom.id = this.id;
        }
        var inner = this.el.dom.firstChild;
        this.progressBar = Ext.get(inner.firstChild);

        if (this.textEl) {

            this.textEl = Ext.get(this.textEl);
            delete this.textTopEl;
        } else {

            this.textTopEl = Ext.get(this.progressBar.dom.firstChild);
            var textBackEl = Ext.get(inner.childNodes[1]);
            this.textTopEl.setStyle("z-index", 99).addClass('x-hidden');
            this.textEl = new Ext.CompositeElement([this.textTopEl.dom.firstChild, textBackEl.dom.firstChild]);
            this.textEl.setWidth(inner.offsetWidth);
        }
        this.progressBar.setHeight(inner.offsetHeight);
    },


    afterRender: function () {
        Ext.ProgressBar.superclass.afterRender.call(this);
        if (this.value) {
            this.updateProgress(this.value, this.text);
        } else {
            this.updateText(this.text);
        }
    },


    updateProgress: function (value, text, animate) {
        this.value = value || 0;
        if (text) {
            this.updateText(text);
        }
        if (this.rendered && !this.isDestroyed) {
            var w = Math.floor(value * this.el.dom.firstChild.offsetWidth);
            this.progressBar.setWidth(w, animate === true || (animate !== false && this.animate));
            if (this.textTopEl) {

                this.textTopEl.removeClass('x-hidden').setWidth(w);
            }
        }
        this.fireEvent('update', this, value, text);
        return this;
    },


    wait: function (o) {
        if (!this.waitTimer) {
            var scope = this;
            o = o || {};
            this.updateText(o.text);
            this.waitTimer = Ext.TaskMgr.start({
                run: function (i) {
                    var inc = o.increment || 10;
                    i -= 1;
                    this.updateProgress(((((i + inc) % inc) + 1) * (100 / inc)) * 0.01, null, o.animate);
                },
                interval: o.interval || 1000,
                duration: o.duration,
                onStop: function () {
                    if (o.fn) {
                        o.fn.apply(o.scope || this);
                    }
                    this.reset();
                },
                scope: scope
            });
        }
        return this;
    },


    isWaiting: function () {
        return this.waitTimer !== null;
    },


    updateText: function (text) {
        this.text = text || '&#160;';
        if (this.rendered) {
            this.textEl.update(this.text);
        }
        return this;
    },


    syncProgressBar: function () {
        if (this.value) {
            this.updateProgress(this.value, this.text);
        }
        return this;
    },


    setSize: function (w, h) {
        Ext.ProgressBar.superclass.setSize.call(this, w, h);
        if (this.textTopEl) {
            var inner = this.el.dom.firstChild;
            this.textEl.setSize(inner.offsetWidth, inner.offsetHeight);
        }
        this.syncProgressBar();
        return this;
    },


    reset: function (hide) {
        this.updateProgress(0);
        if (this.textTopEl) {
            this.textTopEl.addClass('x-hidden');
        }
        this.clearTimer();
        if (hide === true) {
            this.hide();
        }
        return this;
    },


    clearTimer: function () {
        if (this.waitTimer) {
            this.waitTimer.onStop = null;
            Ext.TaskMgr.stop(this.waitTimer);
            this.waitTimer = null;
        }
    },

    onDestroy: function () {
        this.clearTimer();
        if (this.rendered) {
            if (this.textEl.isComposite) {
                this.textEl.clear();
            }
            Ext.destroyMembers(this, 'textEl', 'progressBar', 'textTopEl');
        }
        Ext.ProgressBar.superclass.onDestroy.call(this);
    }
});
Ext.reg('progress', Ext.ProgressBar);

(function () {

    var Event = Ext.EventManager;
    var Dom = Ext.lib.Dom;


    Ext.dd.DragDrop = function (id, sGroup, config) {
        if (id) {
            this.init(id, sGroup, config);
        }
    };

    Ext.dd.DragDrop.prototype = {




        id: null,


        config: null,


        dragElId: null,


        handleElId: null,


        invalidHandleTypes: null,


        invalidHandleIds: null,


        invalidHandleClasses: null,


        startPageX: 0,


        startPageY: 0,


        groups: null,


        locked: false,


        lock: function () {
            this.locked = true;
        },


        moveOnly: false,


        unlock: function () {
            this.locked = false;
        },


        isTarget: true,


        padding: null,


        _domRef: null,


        __ygDragDrop: true,


        constrainX: false,


        constrainY: false,


        minX: 0,


        maxX: 0,


        minY: 0,


        maxY: 0,


        maintainOffset: false,


        xTicks: null,


        yTicks: null,


        primaryButtonOnly: true,


        available: false,


        hasOuterHandles: false,


        b4StartDrag: function (x, y) { },


        startDrag: function (x, y) { },


        b4Drag: function (e) { },


        onDrag: function (e) { },


        onDragEnter: function (e, id) { },


        b4DragOver: function (e) { },


        onDragOver: function (e, id) { },


        b4DragOut: function (e) { },


        onDragOut: function (e, id) { },


        b4DragDrop: function (e) { },


        onDragDrop: function (e, id) { },


        onInvalidDrop: function (e) { },


        b4EndDrag: function (e) { },


        endDrag: function (e) { },


        b4MouseDown: function (e) { },


        onMouseDown: function (e) { },


        onMouseUp: function (e) { },


        onAvailable: function () {
        },


        defaultPadding: { left: 0, right: 0, top: 0, bottom: 0 },


        constrainTo: function (constrainTo, pad, inContent) {
            if (Ext.isNumber(pad)) {
                pad = { left: pad, right: pad, top: pad, bottom: pad };
            }
            pad = pad || this.defaultPadding;
            var b = Ext.get(this.getEl()).getBox(),
            ce = Ext.get(constrainTo),
            s = ce.getScroll(),
            c,
            cd = ce.dom;
            if (cd == document.body) {
                c = { x: s.left, y: s.top, width: Ext.lib.Dom.getViewWidth(), height: Ext.lib.Dom.getViewHeight() };
            } else {
                var xy = ce.getXY();
                c = { x: xy[0], y: xy[1], width: cd.clientWidth, height: cd.clientHeight };
            }


            var topSpace = b.y - c.y,
            leftSpace = b.x - c.x;

            this.resetConstraints();
            this.setXConstraint(leftSpace - (pad.left || 0),
                c.width - leftSpace - b.width - (pad.right || 0),
				this.xTickSize
        );
            this.setYConstraint(topSpace - (pad.top || 0),
                c.height - topSpace - b.height - (pad.bottom || 0),
				this.yTickSize
        );
        },


        getEl: function () {
            if (!this._domRef) {
                this._domRef = Ext.getDom(this.id);
            }

            return this._domRef;
        },


        getDragEl: function () {
            return Ext.getDom(this.dragElId);
        },


        init: function (id, sGroup, config) {
            this.initTarget(id, sGroup, config);
            Event.on(this.id, "mousedown", this.handleMouseDown, this);

        },


        initTarget: function (id, sGroup, config) {


            this.config = config || {};


            this.DDM = Ext.dd.DDM;

            this.groups = {};



            if (typeof id !== "string") {
                id = Ext.id(id);
            }


            this.id = id;


            this.addToGroup((sGroup) ? sGroup : "default");



            this.handleElId = id;


            this.setDragElId(id);


            this.invalidHandleTypes = { A: "A" };
            this.invalidHandleIds = {};
            this.invalidHandleClasses = [];

            this.applyConfig();

            this.handleOnAvailable();
        },


        applyConfig: function () {



            this.padding = this.config.padding || [0, 0, 0, 0];
            this.isTarget = (this.config.isTarget !== false);
            this.maintainOffset = (this.config.maintainOffset);
            this.primaryButtonOnly = (this.config.primaryButtonOnly !== false);

        },


        handleOnAvailable: function () {
            this.available = true;
            this.resetConstraints();
            this.onAvailable();
        },


        setPadding: function (iTop, iRight, iBot, iLeft) {

            if (!iRight && 0 !== iRight) {
                this.padding = [iTop, iTop, iTop, iTop];
            } else if (!iBot && 0 !== iBot) {
                this.padding = [iTop, iRight, iTop, iRight];
            } else {
                this.padding = [iTop, iRight, iBot, iLeft];
            }
        },


        setInitPosition: function (diffX, diffY) {
            var el = this.getEl();

            if (!this.DDM.verifyEl(el)) {
                return;
            }

            var dx = diffX || 0;
            var dy = diffY || 0;

            var p = Dom.getXY(el);

            this.initPageX = p[0] - dx;
            this.initPageY = p[1] - dy;

            this.lastPageX = p[0];
            this.lastPageY = p[1];

            this.setStartPosition(p);
        },


        setStartPosition: function (pos) {
            var p = pos || Dom.getXY(this.getEl());
            this.deltaSetXY = null;

            this.startPageX = p[0];
            this.startPageY = p[1];
        },


        addToGroup: function (sGroup) {
            this.groups[sGroup] = true;
            this.DDM.regDragDrop(this, sGroup);
        },


        removeFromGroup: function (sGroup) {
            if (this.groups[sGroup]) {
                delete this.groups[sGroup];
            }

            this.DDM.removeDDFromGroup(this, sGroup);
        },


        setDragElId: function (id) {
            this.dragElId = id;
        },


        setHandleElId: function (id) {
            if (typeof id !== "string") {
                id = Ext.id(id);
            }
            this.handleElId = id;
            this.DDM.regHandle(this.id, id);
        },


        setOuterHandleElId: function (id) {
            if (typeof id !== "string") {
                id = Ext.id(id);
            }
            Event.on(id, "mousedown",
                this.handleMouseDown, this);
            this.setHandleElId(id);

            this.hasOuterHandles = true;
        },


        unreg: function () {
            Event.un(this.id, "mousedown",
                this.handleMouseDown);
            this._domRef = null;
            this.DDM._remove(this);
        },

        destroy: function () {
            this.unreg();
        },


        isLocked: function () {
            return (this.DDM.isLocked() || this.locked);
        },


        handleMouseDown: function (e, oDD) {
            if (this.primaryButtonOnly && e.button != 0) {
                return;
            }

            if (this.isLocked()) {
                return;
            }

            this.DDM.refreshCache(this.groups);

            var pt = new Ext.lib.Point(Ext.lib.Event.getPageX(e), Ext.lib.Event.getPageY(e));
            if (!this.hasOuterHandles && !this.DDM.isOverTarget(pt, this)) {
            } else {
                if (this.clickValidator(e)) {


                    this.setStartPosition();

                    this.b4MouseDown(e);
                    this.onMouseDown(e);

                    this.DDM.handleMouseDown(e, this);

                    this.DDM.stopEvent(e);
                } else {


                }
            }
        },

        clickValidator: function (e) {
            var target = e.getTarget();
            return (this.isValidHandleChild(target) &&
                    (this.id == this.handleElId ||
                        this.DDM.handleWasClicked(target, this.id)));
        },


        addInvalidHandleType: function (tagName) {
            var type = tagName.toUpperCase();
            this.invalidHandleTypes[type] = type;
        },


        addInvalidHandleId: function (id) {
            if (typeof id !== "string") {
                id = Ext.id(id);
            }
            this.invalidHandleIds[id] = id;
        },


        addInvalidHandleClass: function (cssClass) {
            this.invalidHandleClasses.push(cssClass);
        },


        removeInvalidHandleType: function (tagName) {
            var type = tagName.toUpperCase();

            delete this.invalidHandleTypes[type];
        },


        removeInvalidHandleId: function (id) {
            if (typeof id !== "string") {
                id = Ext.id(id);
            }
            delete this.invalidHandleIds[id];
        },


        removeInvalidHandleClass: function (cssClass) {
            for (var i = 0, len = this.invalidHandleClasses.length; i < len; ++i) {
                if (this.invalidHandleClasses[i] == cssClass) {
                    delete this.invalidHandleClasses[i];
                }
            }
        },


        isValidHandleChild: function (node) {

            var valid = true;

            var nodeName;
            try {
                nodeName = node.nodeName.toUpperCase();
            } catch (e) {
                nodeName = node.nodeName;
            }
            valid = valid && !this.invalidHandleTypes[nodeName];
            valid = valid && !this.invalidHandleIds[node.id];

            for (var i = 0, len = this.invalidHandleClasses.length; valid && i < len; ++i) {
                valid = !Ext.fly(node).hasClass(this.invalidHandleClasses[i]);
            }


            return valid;

        },


        setXTicks: function (iStartX, iTickSize) {
            this.xTicks = [];
            this.xTickSize = iTickSize;

            var tickMap = {};

            for (var i = this.initPageX; i >= this.minX; i = i - iTickSize) {
                if (!tickMap[i]) {
                    this.xTicks[this.xTicks.length] = i;
                    tickMap[i] = true;
                }
            }

            for (i = this.initPageX; i <= this.maxX; i = i + iTickSize) {
                if (!tickMap[i]) {
                    this.xTicks[this.xTicks.length] = i;
                    tickMap[i] = true;
                }
            }

            this.xTicks.sort(this.DDM.numericSort);
        },


        setYTicks: function (iStartY, iTickSize) {
            this.yTicks = [];
            this.yTickSize = iTickSize;

            var tickMap = {};

            for (var i = this.initPageY; i >= this.minY; i = i - iTickSize) {
                if (!tickMap[i]) {
                    this.yTicks[this.yTicks.length] = i;
                    tickMap[i] = true;
                }
            }

            for (i = this.initPageY; i <= this.maxY; i = i + iTickSize) {
                if (!tickMap[i]) {
                    this.yTicks[this.yTicks.length] = i;
                    tickMap[i] = true;
                }
            }

            this.yTicks.sort(this.DDM.numericSort);
        },


        setXConstraint: function (iLeft, iRight, iTickSize) {
            this.leftConstraint = iLeft;
            this.rightConstraint = iRight;

            this.minX = this.initPageX - iLeft;
            this.maxX = this.initPageX + iRight;
            if (iTickSize) { this.setXTicks(this.initPageX, iTickSize); }

            this.constrainX = true;
        },


        clearConstraints: function () {
            this.constrainX = false;
            this.constrainY = false;
            this.clearTicks();
        },


        clearTicks: function () {
            this.xTicks = null;
            this.yTicks = null;
            this.xTickSize = 0;
            this.yTickSize = 0;
        },


        setYConstraint: function (iUp, iDown, iTickSize) {
            this.topConstraint = iUp;
            this.bottomConstraint = iDown;

            this.minY = this.initPageY - iUp;
            this.maxY = this.initPageY + iDown;
            if (iTickSize) { this.setYTicks(this.initPageY, iTickSize); }

            this.constrainY = true;

        },


        resetConstraints: function () {

            if (this.initPageX || this.initPageX === 0) {

                var dx = (this.maintainOffset) ? this.lastPageX - this.initPageX : 0;
                var dy = (this.maintainOffset) ? this.lastPageY - this.initPageY : 0;

                this.setInitPosition(dx, dy);


            } else {
                this.setInitPosition();
            }

            if (this.constrainX) {
                this.setXConstraint(this.leftConstraint,
                                 this.rightConstraint,
                                 this.xTickSize);
            }

            if (this.constrainY) {
                this.setYConstraint(this.topConstraint,
                                 this.bottomConstraint,
                                 this.yTickSize);
            }
        },


        getTick: function (val, tickArray) {
            if (!tickArray) {


                return val;
            } else if (tickArray[0] >= val) {


                return tickArray[0];
            } else {
                for (var i = 0, len = tickArray.length; i < len; ++i) {
                    var next = i + 1;
                    if (tickArray[next] && tickArray[next] >= val) {
                        var diff1 = val - tickArray[i];
                        var diff2 = tickArray[next] - val;
                        return (diff2 > diff1) ? tickArray[i] : tickArray[next];
                    }
                }



                return tickArray[tickArray.length - 1];
            }
        },


        toString: function () {
            return ("DragDrop " + this.id);
        }

    };

})();




if (!Ext.dd.DragDropMgr) {


    Ext.dd.DragDropMgr = function () {

        var Event = Ext.EventManager;

        return {


            ids: {},


            handleIds: {},


            dragCurrent: null,


            dragOvers: {},


            deltaX: 0,


            deltaY: 0,


            preventDefault: true,


            stopPropagation: true,


            initialized: false,


            locked: false,


            init: function () {
                this.initialized = true;
            },


            POINT: 0,


            INTERSECT: 1,


            mode: 0,


            _execOnAll: function (sMethod, args) {
                for (var i in this.ids) {
                    for (var j in this.ids[i]) {
                        var oDD = this.ids[i][j];
                        if (!this.isTypeOfDD(oDD)) {
                            continue;
                        }
                        oDD[sMethod].apply(oDD, args);
                    }
                }
            },


            _onLoad: function () {

                this.init();


                Event.on(document, "mouseup", this.handleMouseUp, this, true);
                Event.on(document, "mousemove", this.handleMouseMove, this, true);
                Event.on(window, "unload", this._onUnload, this, true);
                Event.on(window, "resize", this._onResize, this, true);


            },


            _onResize: function (e) {
                this._execOnAll("resetConstraints", []);
            },


            lock: function () { this.locked = true; },


            unlock: function () { this.locked = false; },


            isLocked: function () { return this.locked; },


            locationCache: {},


            useCache: true,


            clickPixelThresh: 3,


            clickTimeThresh: 350,


            dragThreshMet: false,


            clickTimeout: null,


            startX: 0,


            startY: 0,


            regDragDrop: function (oDD, sGroup) {
                if (!this.initialized) { this.init(); }

                if (!this.ids[sGroup]) {
                    this.ids[sGroup] = {};
                }
                this.ids[sGroup][oDD.id] = oDD;
            },


            removeDDFromGroup: function (oDD, sGroup) {
                if (!this.ids[sGroup]) {
                    this.ids[sGroup] = {};
                }

                var obj = this.ids[sGroup];
                if (obj && obj[oDD.id]) {
                    delete obj[oDD.id];
                }
            },


            _remove: function (oDD) {
                for (var g in oDD.groups) {
                    if (g && this.ids[g] && this.ids[g][oDD.id]) {
                        delete this.ids[g][oDD.id];
                    }
                }
                delete this.handleIds[oDD.id];
            },


            regHandle: function (sDDId, sHandleId) {
                if (!this.handleIds[sDDId]) {
                    this.handleIds[sDDId] = {};
                }
                this.handleIds[sDDId][sHandleId] = sHandleId;
            },


            isDragDrop: function (id) {
                return (this.getDDById(id)) ? true : false;
            },


            getRelated: function (p_oDD, bTargetsOnly) {
                var oDDs = [];
                for (var i in p_oDD.groups) {
                    for (var j in this.ids[i]) {
                        var dd = this.ids[i][j];
                        if (!this.isTypeOfDD(dd)) {
                            continue;
                        }
                        if (!bTargetsOnly || dd.isTarget) {
                            oDDs[oDDs.length] = dd;
                        }
                    }
                }

                return oDDs;
            },


            isLegalTarget: function (oDD, oTargetDD) {
                var targets = this.getRelated(oDD, true);
                for (var i = 0, len = targets.length; i < len; ++i) {
                    if (targets[i].id == oTargetDD.id) {
                        return true;
                    }
                }

                return false;
            },


            isTypeOfDD: function (oDD) {
                return (oDD && oDD.__ygDragDrop);
            },


            isHandle: function (sDDId, sHandleId) {
                return (this.handleIds[sDDId] &&
                            this.handleIds[sDDId][sHandleId]);
            },


            getDDById: function (id) {
                for (var i in this.ids) {
                    if (this.ids[i][id]) {
                        return this.ids[i][id];
                    }
                }
                return null;
            },


            handleMouseDown: function (e, oDD) {
                if (Ext.QuickTips) {
                    Ext.QuickTips.ddDisable();
                }
                if (this.dragCurrent) {


                    this.handleMouseUp(e);
                }

                this.currentTarget = e.getTarget();
                this.dragCurrent = oDD;

                var el = oDD.getEl();


                this.startX = e.getPageX();
                this.startY = e.getPageY();

                this.deltaX = this.startX - el.offsetLeft;
                this.deltaY = this.startY - el.offsetTop;

                this.dragThreshMet = false;

                this.clickTimeout = setTimeout(
                    function () {
                        var DDM = Ext.dd.DDM;
                        DDM.startDrag(DDM.startX, DDM.startY);
                    },
                    this.clickTimeThresh);
            },


            startDrag: function (x, y) {
                clearTimeout(this.clickTimeout);
                if (this.dragCurrent) {
                    this.dragCurrent.b4StartDrag(x, y);
                    this.dragCurrent.startDrag(x, y);
                }
                this.dragThreshMet = true;
            },


            handleMouseUp: function (e) {

                if (Ext.QuickTips) {
                    Ext.QuickTips.ddEnable();
                }
                if (!this.dragCurrent) {
                    return;
                }

                clearTimeout(this.clickTimeout);

                if (this.dragThreshMet) {
                    this.fireEvents(e, true);
                } else {
                }

                this.stopDrag(e);

                this.stopEvent(e);
            },


            stopEvent: function (e) {
                if (this.stopPropagation) {
                    e.stopPropagation();
                }

                if (this.preventDefault) {
                    e.preventDefault();
                }
            },


            stopDrag: function (e) {

                if (this.dragCurrent) {
                    if (this.dragThreshMet) {
                        this.dragCurrent.b4EndDrag(e);
                        this.dragCurrent.endDrag(e);
                    }

                    this.dragCurrent.onMouseUp(e);
                }

                this.dragCurrent = null;
                this.dragOvers = {};
            },


            handleMouseMove: function (e) {
                if (!this.dragCurrent) {
                    return true;
                }



                if (Ext.isIE && (e.button !== 0 && e.button !== 1 && e.button !== 2)) {
                    this.stopEvent(e);
                    return this.handleMouseUp(e);
                }

                if (!this.dragThreshMet) {
                    var diffX = Math.abs(this.startX - e.getPageX());
                    var diffY = Math.abs(this.startY - e.getPageY());
                    if (diffX > this.clickPixelThresh ||
                            diffY > this.clickPixelThresh) {
                        this.startDrag(this.startX, this.startY);
                    }
                }

                if (this.dragThreshMet) {
                    this.dragCurrent.b4Drag(e);
                    this.dragCurrent.onDrag(e);
                    if (!this.dragCurrent.moveOnly) {
                        this.fireEvents(e, false);
                    }
                }

                this.stopEvent(e);

                return true;
            },


            fireEvents: function (e, isDrop) {
                var dc = this.dragCurrent;



                if (!dc || dc.isLocked()) {
                    return;
                }

                var pt = e.getPoint();


                var oldOvers = [];

                var outEvts = [];
                var overEvts = [];
                var dropEvts = [];
                var enterEvts = [];



                for (var i in this.dragOvers) {

                    var ddo = this.dragOvers[i];

                    if (!this.isTypeOfDD(ddo)) {
                        continue;
                    }

                    if (!this.isOverTarget(pt, ddo, this.mode)) {
                        outEvts.push(ddo);
                    }

                    oldOvers[i] = true;
                    delete this.dragOvers[i];
                }

                for (var sGroup in dc.groups) {

                    if ("string" != typeof sGroup) {
                        continue;
                    }

                    for (i in this.ids[sGroup]) {
                        var oDD = this.ids[sGroup][i];
                        if (!this.isTypeOfDD(oDD)) {
                            continue;
                        }

                        if (oDD.isTarget && !oDD.isLocked() && ((oDD != dc) || (dc.ignoreSelf === false))) {
                            if (this.isOverTarget(pt, oDD, this.mode)) {

                                if (isDrop) {
                                    dropEvts.push(oDD);

                                } else {


                                    if (!oldOvers[oDD.id]) {
                                        enterEvts.push(oDD);

                                    } else {
                                        overEvts.push(oDD);
                                    }

                                    this.dragOvers[oDD.id] = oDD;
                                }
                            }
                        }
                    }
                }

                if (this.mode) {
                    if (outEvts.length) {
                        dc.b4DragOut(e, outEvts);
                        dc.onDragOut(e, outEvts);
                    }

                    if (enterEvts.length) {
                        dc.onDragEnter(e, enterEvts);
                    }

                    if (overEvts.length) {
                        dc.b4DragOver(e, overEvts);
                        dc.onDragOver(e, overEvts);
                    }

                    if (dropEvts.length) {
                        dc.b4DragDrop(e, dropEvts);
                        dc.onDragDrop(e, dropEvts);
                    }

                } else {

                    var len = 0;
                    for (i = 0, len = outEvts.length; i < len; ++i) {
                        dc.b4DragOut(e, outEvts[i].id);
                        dc.onDragOut(e, outEvts[i].id);
                    }


                    for (i = 0, len = enterEvts.length; i < len; ++i) {

                        dc.onDragEnter(e, enterEvts[i].id);
                    }


                    for (i = 0, len = overEvts.length; i < len; ++i) {
                        dc.b4DragOver(e, overEvts[i].id);
                        dc.onDragOver(e, overEvts[i].id);
                    }


                    for (i = 0, len = dropEvts.length; i < len; ++i) {
                        dc.b4DragDrop(e, dropEvts[i].id);
                        dc.onDragDrop(e, dropEvts[i].id);
                    }

                }


                if (isDrop && !dropEvts.length) {
                    dc.onInvalidDrop(e);
                }

            },


            getBestMatch: function (dds) {
                var winner = null;






                var len = dds.length;

                if (len == 1) {
                    winner = dds[0];
                } else {

                    for (var i = 0; i < len; ++i) {
                        var dd = dds[i];



                        if (dd.cursorIsOver) {
                            winner = dd;
                            break;

                        } else {
                            if (!winner ||
                            winner.overlap.getArea() < dd.overlap.getArea()) {
                                winner = dd;
                            }
                        }
                    }
                }

                return winner;
            },


            refreshCache: function (groups) {
                for (var sGroup in groups) {
                    if ("string" != typeof sGroup) {
                        continue;
                    }
                    for (var i in this.ids[sGroup]) {
                        var oDD = this.ids[sGroup][i];

                        if (this.isTypeOfDD(oDD)) {

                            var loc = this.getLocation(oDD);
                            if (loc) {
                                this.locationCache[oDD.id] = loc;
                            } else {
                                delete this.locationCache[oDD.id];



                            }
                        }
                    }
                }
            },


            verifyEl: function (el) {
                if (el) {
                    var parent;
                    if (Ext.isIE) {
                        try {
                            parent = el.offsetParent;
                        } catch (e) { }
                    } else {
                        parent = el.offsetParent;
                    }
                    if (parent) {
                        return true;
                    }
                }

                return false;
            },


            getLocation: function (oDD) {
                if (!this.isTypeOfDD(oDD)) {
                    return null;
                }

                var el = oDD.getEl(), pos, x1, x2, y1, y2, t, r, b, l;

                try {
                    pos = Ext.lib.Dom.getXY(el);
                } catch (e) { }

                if (!pos) {
                    return null;
                }

                x1 = pos[0];
                x2 = x1 + el.offsetWidth;
                y1 = pos[1];
                y2 = y1 + el.offsetHeight;

                t = y1 - oDD.padding[0];
                r = x2 + oDD.padding[1];
                b = y2 + oDD.padding[2];
                l = x1 - oDD.padding[3];

                return new Ext.lib.Region(t, r, b, l);
            },


            isOverTarget: function (pt, oTarget, intersect) {

                var loc = this.locationCache[oTarget.id];
                if (!loc || !this.useCache) {
                    loc = this.getLocation(oTarget);
                    this.locationCache[oTarget.id] = loc;

                }

                if (!loc) {
                    return false;
                }

                oTarget.cursorIsOver = loc.contains(pt);






                var dc = this.dragCurrent;
                if (!dc || !dc.getTargetCoord ||
                    (!intersect && !dc.constrainX && !dc.constrainY)) {
                    return oTarget.cursorIsOver;
                }

                oTarget.overlap = null;





                var pos = dc.getTargetCoord(pt.x, pt.y);

                var el = dc.getDragEl();
                var curRegion = new Ext.lib.Region(pos.y,
                                                   pos.x + el.offsetWidth,
                                                   pos.y + el.offsetHeight,
                                                   pos.x);

                var overlap = curRegion.intersect(loc);

                if (overlap) {
                    oTarget.overlap = overlap;
                    return (intersect) ? true : oTarget.cursorIsOver;
                } else {
                    return false;
                }
            },


            _onUnload: function (e, me) {
                Ext.dd.DragDropMgr.unregAll();
            },


            unregAll: function () {

                if (this.dragCurrent) {
                    this.stopDrag();
                    this.dragCurrent = null;
                }

                this._execOnAll("unreg", []);

                for (var i in this.elementCache) {
                    delete this.elementCache[i];
                }

                this.elementCache = {};
                this.ids = {};
            },


            elementCache: {},


            getElWrapper: function (id) {
                var oWrapper = this.elementCache[id];
                if (!oWrapper || !oWrapper.el) {
                    oWrapper = this.elementCache[id] =
                    new this.ElementWrapper(Ext.getDom(id));
                }
                return oWrapper;
            },


            getElement: function (id) {
                return Ext.getDom(id);
            },


            getCss: function (id) {
                var el = Ext.getDom(id);
                return (el) ? el.style : null;
            },


            ElementWrapper: function (el) {

                this.el = el || null;

                this.id = this.el && el.id;

                this.css = this.el && el.style;
            },


            getPosX: function (el) {
                return Ext.lib.Dom.getX(el);
            },


            getPosY: function (el) {
                return Ext.lib.Dom.getY(el);
            },


            swapNode: function (n1, n2) {
                if (n1.swapNode) {
                    n1.swapNode(n2);
                } else {
                    var p = n2.parentNode;
                    var s = n2.nextSibling;

                    if (s == n1) {
                        p.insertBefore(n1, n2);
                    } else if (n2 == n1.nextSibling) {
                        p.insertBefore(n2, n1);
                    } else {
                        n1.parentNode.replaceChild(n2, n1);
                        p.insertBefore(n1, s);
                    }
                }
            },


            getScroll: function () {
                var t, l, dde = document.documentElement, db = document.body;
                if (dde && (dde.scrollTop || dde.scrollLeft)) {
                    t = dde.scrollTop;
                    l = dde.scrollLeft;
                } else if (db) {
                    t = db.scrollTop;
                    l = db.scrollLeft;
                } else {

                }
                return { top: t, left: l };
            },


            getStyle: function (el, styleProp) {
                return Ext.fly(el).getStyle(styleProp);
            },


            getScrollTop: function () {
                return this.getScroll().top;
            },


            getScrollLeft: function () {
                return this.getScroll().left;
            },


            moveToEl: function (moveEl, targetEl) {
                var aCoord = Ext.lib.Dom.getXY(targetEl);
                Ext.lib.Dom.setXY(moveEl, aCoord);
            },


            numericSort: function (a, b) {
                return (a - b);
            },


            _timeoutCount: 0,


            _addListeners: function () {
                var DDM = Ext.dd.DDM;
                if (Ext.lib.Event && document) {
                    DDM._onLoad();
                } else {
                    if (DDM._timeoutCount > 2000) {
                    } else {
                        setTimeout(DDM._addListeners, 10);
                        if (document && document.body) {
                            DDM._timeoutCount += 1;
                        }
                    }
                }
            },


            handleWasClicked: function (node, id) {
                if (this.isHandle(id, node.id)) {
                    return true;
                } else {

                    var p = node.parentNode;

                    while (p) {
                        if (this.isHandle(id, p.id)) {
                            return true;
                        } else {
                            p = p.parentNode;
                        }
                    }
                }

                return false;
            }

        };

    } ();


    Ext.dd.DDM = Ext.dd.DragDropMgr;
    Ext.dd.DDM._addListeners();

}


Ext.dd.DD = function (id, sGroup, config) {
    if (id) {
        this.init(id, sGroup, config);
    }
};

Ext.extend(Ext.dd.DD, Ext.dd.DragDrop, {


    scroll: true,


    autoOffset: function (iPageX, iPageY) {
        var x = iPageX - this.startPageX;
        var y = iPageY - this.startPageY;
        this.setDelta(x, y);
    },


    setDelta: function (iDeltaX, iDeltaY) {
        this.deltaX = iDeltaX;
        this.deltaY = iDeltaY;
    },


    setDragElPos: function (iPageX, iPageY) {



        var el = this.getDragEl();
        this.alignElWithMouse(el, iPageX, iPageY);
    },


    alignElWithMouse: function (el, iPageX, iPageY) {
        var oCoord = this.getTargetCoord(iPageX, iPageY);
        var fly = el.dom ? el : Ext.fly(el, '_dd');
        if (!this.deltaSetXY) {
            var aCoord = [oCoord.x, oCoord.y];
            fly.setXY(aCoord);
            var newLeft = fly.getLeft(true);
            var newTop = fly.getTop(true);
            this.deltaSetXY = [newLeft - oCoord.x, newTop - oCoord.y];
        } else {
            fly.setLeftTop(oCoord.x + this.deltaSetXY[0], oCoord.y + this.deltaSetXY[1]);
        }

        this.cachePosition(oCoord.x, oCoord.y);
        this.autoScroll(oCoord.x, oCoord.y, el.offsetHeight, el.offsetWidth);
        return oCoord;
    },


    cachePosition: function (iPageX, iPageY) {
        if (iPageX) {
            this.lastPageX = iPageX;
            this.lastPageY = iPageY;
        } else {
            var aCoord = Ext.lib.Dom.getXY(this.getEl());
            this.lastPageX = aCoord[0];
            this.lastPageY = aCoord[1];
        }
    },


    autoScroll: function (x, y, h, w) {

        if (this.scroll) {

            var clientH = Ext.lib.Dom.getViewHeight();


            var clientW = Ext.lib.Dom.getViewWidth();


            var st = this.DDM.getScrollTop();


            var sl = this.DDM.getScrollLeft();


            var bot = h + y;


            var right = w + x;




            var toBot = (clientH + st - y - this.deltaY);


            var toRight = (clientW + sl - x - this.deltaX);




            var thresh = 40;




            var scrAmt = (document.all) ? 80 : 30;



            if (bot > clientH && toBot < thresh) {
                window.scrollTo(sl, st + scrAmt);
            }



            if (y < st && st > 0 && y - st < thresh) {
                window.scrollTo(sl, st - scrAmt);
            }



            if (right > clientW && toRight < thresh) {
                window.scrollTo(sl + scrAmt, st);
            }



            if (x < sl && sl > 0 && x - sl < thresh) {
                window.scrollTo(sl - scrAmt, st);
            }
        }
    },


    getTargetCoord: function (iPageX, iPageY) {
        var x = iPageX - this.deltaX;
        var y = iPageY - this.deltaY;

        if (this.constrainX) {
            if (x < this.minX) { x = this.minX; }
            if (x > this.maxX) { x = this.maxX; }
        }

        if (this.constrainY) {
            if (y < this.minY) { y = this.minY; }
            if (y > this.maxY) { y = this.maxY; }
        }

        x = this.getTick(x, this.xTicks);
        y = this.getTick(y, this.yTicks);


        return { x: x, y: y };
    },


    applyConfig: function () {
        Ext.dd.DD.superclass.applyConfig.call(this);
        this.scroll = (this.config.scroll !== false);
    },


    b4MouseDown: function (e) {

        this.autoOffset(e.getPageX(),
                            e.getPageY());
    },


    b4Drag: function (e) {
        this.setDragElPos(e.getPageX(),
                            e.getPageY());
    },

    toString: function () {
        return ("DD " + this.id);
    }






});

Ext.dd.DDProxy = function (id, sGroup, config) {
    if (id) {
        this.init(id, sGroup, config);
        this.initFrame();
    }
};


Ext.dd.DDProxy.dragElId = "ygddfdiv";

Ext.extend(Ext.dd.DDProxy, Ext.dd.DD, {


    resizeFrame: true,


    centerFrame: false,


    createFrame: function () {
        var self = this;
        var body = document.body;

        if (!body || !body.firstChild) {
            setTimeout(function () { self.createFrame(); }, 50);
            return;
        }

        var div = this.getDragEl();

        if (!div) {
            div = document.createElement("div");
            div.id = this.dragElId;
            var s = div.style;

            s.position = "absolute";
            s.visibility = "hidden";
            s.cursor = "move";
            s.border = "2px solid #aaa";
            s.zIndex = 999;




            body.insertBefore(div, body.firstChild);
        }
    },


    initFrame: function () {
        this.createFrame();
    },

    applyConfig: function () {
        Ext.dd.DDProxy.superclass.applyConfig.call(this);

        this.resizeFrame = (this.config.resizeFrame !== false);
        this.centerFrame = (this.config.centerFrame);
        this.setDragElId(this.config.dragElId || Ext.dd.DDProxy.dragElId);
    },


    showFrame: function (iPageX, iPageY) {
        var el = this.getEl();
        var dragEl = this.getDragEl();
        var s = dragEl.style;

        this._resizeProxy();

        if (this.centerFrame) {
            this.setDelta(Math.round(parseInt(s.width, 10) / 2),
                           Math.round(parseInt(s.height, 10) / 2));
        }

        this.setDragElPos(iPageX, iPageY);

        Ext.fly(dragEl).show();
    },


    _resizeProxy: function () {
        if (this.resizeFrame) {
            var el = this.getEl();
            Ext.fly(this.getDragEl()).setSize(el.offsetWidth, el.offsetHeight);
        }
    },


    b4MouseDown: function (e) {
        var x = e.getPageX();
        var y = e.getPageY();
        this.autoOffset(x, y);
        this.setDragElPos(x, y);
    },


    b4StartDrag: function (x, y) {

        this.showFrame(x, y);
    },


    b4EndDrag: function (e) {
        Ext.fly(this.getDragEl()).hide();
    },




    endDrag: function (e) {

        var lel = this.getEl();
        var del = this.getDragEl();


        del.style.visibility = "";

        this.beforeMove();


        lel.style.visibility = "hidden";
        Ext.dd.DDM.moveToEl(lel, del);
        del.style.visibility = "hidden";
        lel.style.visibility = "";

        this.afterDrag();
    },

    beforeMove: function () {

    },

    afterDrag: function () {

    },

    toString: function () {
        return ("DDProxy " + this.id);
    }

});

Ext.dd.DDTarget = function (id, sGroup, config) {
    if (id) {
        this.initTarget(id, sGroup, config);
    }
};


Ext.extend(Ext.dd.DDTarget, Ext.dd.DragDrop, {

    getDragEl: Ext.emptyFn,

    isValidHandleChild: Ext.emptyFn,

    startDrag: Ext.emptyFn,

    endDrag: Ext.emptyFn,

    onDrag: Ext.emptyFn,

    onDragDrop: Ext.emptyFn,

    onDragEnter: Ext.emptyFn,

    onDragOut: Ext.emptyFn,

    onDragOver: Ext.emptyFn,

    onInvalidDrop: Ext.emptyFn,

    onMouseDown: Ext.emptyFn,

    onMouseUp: Ext.emptyFn,

    setXConstraint: Ext.emptyFn,

    setYConstraint: Ext.emptyFn,

    resetConstraints: Ext.emptyFn,

    clearConstraints: Ext.emptyFn,

    clearTicks: Ext.emptyFn,

    setInitPosition: Ext.emptyFn,

    setDragElId: Ext.emptyFn,

    setHandleElId: Ext.emptyFn,

    setOuterHandleElId: Ext.emptyFn,

    addInvalidHandleClass: Ext.emptyFn,

    addInvalidHandleId: Ext.emptyFn,

    addInvalidHandleType: Ext.emptyFn,

    removeInvalidHandleClass: Ext.emptyFn,

    removeInvalidHandleId: Ext.emptyFn,

    removeInvalidHandleType: Ext.emptyFn,

    toString: function () {
        return ("DDTarget " + this.id);
    }
});
Ext.dd.DragTracker = Ext.extend(Ext.util.Observable, {

    active: false,

    tolerance: 5,

    autoStart: false,

    constructor: function (config) {
        Ext.apply(this, config);
        this.addEvents(

	        'mousedown',

	        'mouseup',

	        'mousemove',

	        'dragstart',

	        'dragend',

	        'drag'
	    );

        this.dragRegion = new Ext.lib.Region(0, 0, 0, 0);

        if (this.el) {
            this.initEl(this.el);
        }
        Ext.dd.DragTracker.superclass.constructor.call(this, config);
    },

    initEl: function (el) {
        this.el = Ext.get(el);
        el.on('mousedown', this.onMouseDown, this,
                this.delegate ? { delegate: this.delegate} : undefined);
    },

    destroy: function () {
        this.el.un('mousedown', this.onMouseDown, this);
        delete this.el;
    },

    onMouseDown: function (e, target) {
        if (this.fireEvent('mousedown', this, e) !== false && this.onBeforeStart(e) !== false) {
            this.startXY = this.lastXY = e.getXY();
            this.dragTarget = this.delegate ? target : this.el.dom;
            if (this.preventDefault !== false) {
                e.preventDefault();
            }
            Ext.getDoc().on({
                scope: this,
                mouseup: this.onMouseUp,
                mousemove: this.onMouseMove,
                selectstart: this.stopSelect
            });
            if (this.autoStart) {
                this.timer = this.triggerStart.defer(this.autoStart === true ? 1000 : this.autoStart, this, [e]);
            }
        }
    },

    onMouseMove: function (e, target) {

        if (this.active && Ext.isIE && !e.browserEvent.button) {
            e.preventDefault();
            this.onMouseUp(e);
            return;
        }

        e.preventDefault();
        var xy = e.getXY(), s = this.startXY;
        this.lastXY = xy;
        if (!this.active) {
            if (Math.abs(s[0] - xy[0]) > this.tolerance || Math.abs(s[1] - xy[1]) > this.tolerance) {
                this.triggerStart(e);
            } else {
                return;
            }
        }
        this.fireEvent('mousemove', this, e);
        this.onDrag(e);
        this.fireEvent('drag', this, e);
    },

    onMouseUp: function (e) {
        var doc = Ext.getDoc(),
            wasActive = this.active;

        doc.un('mousemove', this.onMouseMove, this);
        doc.un('mouseup', this.onMouseUp, this);
        doc.un('selectstart', this.stopSelect, this);
        e.preventDefault();
        this.clearStart();
        this.active = false;
        delete this.elRegion;
        this.fireEvent('mouseup', this, e);
        if (wasActive) {
            this.onEnd(e);
            this.fireEvent('dragend', this, e);
        }
    },

    triggerStart: function (e) {
        this.clearStart();
        this.active = true;
        this.onStart(e);
        this.fireEvent('dragstart', this, e);
    },

    clearStart: function () {
        if (this.timer) {
            clearTimeout(this.timer);
            delete this.timer;
        }
    },

    stopSelect: function (e) {
        e.stopEvent();
        return false;
    },


    onBeforeStart: function (e) {

    },


    onStart: function (xy) {

    },


    onDrag: function (e) {

    },


    onEnd: function (e) {

    },


    getDragTarget: function () {
        return this.dragTarget;
    },

    getDragCt: function () {
        return this.el;
    },

    getXY: function (constrain) {
        return constrain ?
               this.constrainModes[constrain].call(this, this.lastXY) : this.lastXY;
    },

    getOffset: function (constrain) {
        var xy = this.getXY(constrain),
            s = this.startXY;
        return [s[0] - xy[0], s[1] - xy[1]];
    },

    constrainModes: {
        'point': function (xy) {

            if (!this.elRegion) {
                this.elRegion = this.getDragCt().getRegion();
            }

            var dr = this.dragRegion;

            dr.left = xy[0];
            dr.top = xy[1];
            dr.right = xy[0];
            dr.bottom = xy[1];

            dr.constrainTo(this.elRegion);

            return [dr.left, dr.top];
        }
    }
});
Ext.dd.ScrollManager = function () {
    var ddm = Ext.dd.DragDropMgr;
    var els = {};
    var dragEl = null;
    var proc = {};

    var onStop = function (e) {
        dragEl = null;
        clearProc();
    };

    var triggerRefresh = function () {
        if (ddm.dragCurrent) {
            ddm.refreshCache(ddm.dragCurrent.groups);
        }
    };

    var doScroll = function () {
        if (ddm.dragCurrent) {
            var dds = Ext.dd.ScrollManager;
            var inc = proc.el.ddScrollConfig ?
                      proc.el.ddScrollConfig.increment : dds.increment;
            if (!dds.animate) {
                if (proc.el.scroll(proc.dir, inc)) {
                    triggerRefresh();
                }
            } else {
                proc.el.scroll(proc.dir, inc, true, dds.animDuration, triggerRefresh);
            }
        }
    };

    var clearProc = function () {
        if (proc.id) {
            clearInterval(proc.id);
        }
        proc.id = 0;
        proc.el = null;
        proc.dir = "";
    };

    var startProc = function (el, dir) {
        clearProc();
        proc.el = el;
        proc.dir = dir;
        var group = el.ddScrollConfig ? el.ddScrollConfig.ddGroup : undefined,
            freq = (el.ddScrollConfig && el.ddScrollConfig.frequency)
                  ? el.ddScrollConfig.frequency
                  : Ext.dd.ScrollManager.frequency;

        if (group === undefined || ddm.dragCurrent.ddGroup == group) {
            proc.id = setInterval(doScroll, freq);
        }
    };

    var onFire = function (e, isDrop) {
        if (isDrop || !ddm.dragCurrent) { return; }
        var dds = Ext.dd.ScrollManager;
        if (!dragEl || dragEl != ddm.dragCurrent) {
            dragEl = ddm.dragCurrent;

            dds.refreshCache();
        }

        var xy = Ext.lib.Event.getXY(e);
        var pt = new Ext.lib.Point(xy[0], xy[1]);
        for (var id in els) {
            var el = els[id], r = el._region;
            var c = el.ddScrollConfig ? el.ddScrollConfig : dds;
            if (r && r.contains(pt) && el.isScrollable()) {
                if (r.bottom - pt.y <= c.vthresh) {
                    if (proc.el != el) {
                        startProc(el, "down");
                    }
                    return;
                } else if (r.right - pt.x <= c.hthresh) {
                    if (proc.el != el) {
                        startProc(el, "left");
                    }
                    return;
                } else if (pt.y - r.top <= c.vthresh) {
                    if (proc.el != el) {
                        startProc(el, "up");
                    }
                    return;
                } else if (pt.x - r.left <= c.hthresh) {
                    if (proc.el != el) {
                        startProc(el, "right");
                    }
                    return;
                }
            }
        }
        clearProc();
    };

    ddm.fireEvents = ddm.fireEvents.createSequence(onFire, ddm);
    ddm.stopDrag = ddm.stopDrag.createSequence(onStop, ddm);

    return {

        register: function (el) {
            if (Ext.isArray(el)) {
                for (var i = 0, len = el.length; i < len; i++) {
                    this.register(el[i]);
                }
            } else {
                el = Ext.get(el);
                els[el.id] = el;
            }
        },


        unregister: function (el) {
            if (Ext.isArray(el)) {
                for (var i = 0, len = el.length; i < len; i++) {
                    this.unregister(el[i]);
                }
            } else {
                el = Ext.get(el);
                delete els[el.id];
            }
        },


        vthresh: 25,

        hthresh: 25,


        increment: 100,


        frequency: 500,


        animate: true,


        animDuration: .4,


        ddGroup: undefined,


        refreshCache: function () {
            for (var id in els) {
                if (typeof els[id] == 'object') {
                    els[id]._region = els[id].getRegion();
                }
            }
        }
    };
} ();
Ext.dd.Registry = function () {
    var elements = {};
    var handles = {};
    var autoIdSeed = 0;

    var getId = function (el, autogen) {
        if (typeof el == "string") {
            return el;
        }
        var id = el.id;
        if (!id && autogen !== false) {
            id = "extdd-" + (++autoIdSeed);
            el.id = id;
        }
        return id;
    };

    return {

        register: function (el, data) {
            data = data || {};
            if (typeof el == "string") {
                el = document.getElementById(el);
            }
            data.ddel = el;
            elements[getId(el)] = data;
            if (data.isHandle !== false) {
                handles[data.ddel.id] = data;
            }
            if (data.handles) {
                var hs = data.handles;
                for (var i = 0, len = hs.length; i < len; i++) {
                    handles[getId(hs[i])] = data;
                }
            }
        },


        unregister: function (el) {
            var id = getId(el, false);
            var data = elements[id];
            if (data) {
                delete elements[id];
                if (data.handles) {
                    var hs = data.handles;
                    for (var i = 0, len = hs.length; i < len; i++) {
                        delete handles[getId(hs[i], false)];
                    }
                }
            }
        },


        getHandle: function (id) {
            if (typeof id != "string") {
                id = id.id;
            }
            return handles[id];
        },


        getHandleFromEvent: function (e) {
            var t = Ext.lib.Event.getTarget(e);
            return t ? handles[t.id] : null;
        },


        getTarget: function (id) {
            if (typeof id != "string") {
                id = id.id;
            }
            return elements[id];
        },


        getTargetFromEvent: function (e) {
            var t = Ext.lib.Event.getTarget(e);
            return t ? elements[t.id] || handles[t.id] : null;
        }
    };
} ();
Ext.dd.StatusProxy = function (config) {
    Ext.apply(this, config);
    this.id = this.id || Ext.id();
    this.el = new Ext.Layer({
        dh: {
            id: this.id, tag: "div", cls: "x-dd-drag-proxy " + this.dropNotAllowed, children: [
                { tag: "div", cls: "x-dd-drop-icon" },
                { tag: "div", cls: "x-dd-drag-ghost" }
            ]
        },
        shadow: !config || config.shadow !== false
    });
    this.ghost = Ext.get(this.el.dom.childNodes[1]);
    this.dropStatus = this.dropNotAllowed;
};

Ext.dd.StatusProxy.prototype = {

    dropAllowed: "x-dd-drop-ok",

    dropNotAllowed: "x-dd-drop-nodrop",


    setStatus: function (cssClass) {
        cssClass = cssClass || this.dropNotAllowed;
        if (this.dropStatus != cssClass) {
            this.el.replaceClass(this.dropStatus, cssClass);
            this.dropStatus = cssClass;
        }
    },


    reset: function (clearGhost) {
        this.el.dom.className = "x-dd-drag-proxy " + this.dropNotAllowed;
        this.dropStatus = this.dropNotAllowed;
        if (clearGhost) {
            this.ghost.update("");
        }
    },


    update: function (html) {
        if (typeof html == "string") {
            this.ghost.update(html);
        } else {
            this.ghost.update("");
            html.style.margin = "0";
            this.ghost.dom.appendChild(html);
        }
        var el = this.ghost.dom.firstChild;
        if (el) {
            Ext.fly(el).setStyle('float', 'none');
        }
    },


    getEl: function () {
        return this.el;
    },


    getGhost: function () {
        return this.ghost;
    },


    hide: function (clear) {
        this.el.hide();
        if (clear) {
            this.reset(true);
        }
    },


    stop: function () {
        if (this.anim && this.anim.isAnimated && this.anim.isAnimated()) {
            this.anim.stop();
        }
    },


    show: function () {
        this.el.show();
    },


    sync: function () {
        this.el.sync();
    },


    repair: function (xy, callback, scope) {
        this.callback = callback;
        this.scope = scope;
        if (xy && this.animRepair !== false) {
            this.el.addClass("x-dd-drag-repair");
            this.el.hideUnders(true);
            this.anim = this.el.shift({
                duration: this.repairDuration || .5,
                easing: 'easeOut',
                xy: xy,
                stopFx: true,
                callback: this.afterRepair,
                scope: this
            });
        } else {
            this.afterRepair();
        }
    },


    afterRepair: function () {
        this.hide(true);
        if (typeof this.callback == "function") {
            this.callback.call(this.scope || this);
        }
        this.callback = null;
        this.scope = null;
    },

    destroy: function () {
        Ext.destroy(this.ghost, this.el);
    }
};
Ext.dd.DragSource = function (el, config) {
    this.el = Ext.get(el);
    if (!this.dragData) {
        this.dragData = {};
    }

    Ext.apply(this, config);

    if (!this.proxy) {
        this.proxy = new Ext.dd.StatusProxy();
    }
    Ext.dd.DragSource.superclass.constructor.call(this, this.el.dom, this.ddGroup || this.group,
          { dragElId: this.proxy.id, resizeFrame: false, isTarget: false, scroll: this.scroll === true });

    this.dragging = false;
};

Ext.extend(Ext.dd.DragSource, Ext.dd.DDProxy, {


    dropAllowed: "x-dd-drop-ok",

    dropNotAllowed: "x-dd-drop-nodrop",


    getDragData: function (e) {
        return this.dragData;
    },


    onDragEnter: function (e, id) {
        var target = Ext.dd.DragDropMgr.getDDById(id);
        this.cachedTarget = target;
        if (this.beforeDragEnter(target, e, id) !== false) {
            if (target.isNotifyTarget) {
                var status = target.notifyEnter(this, e, this.dragData);
                this.proxy.setStatus(status);
            } else {
                this.proxy.setStatus(this.dropAllowed);
            }

            if (this.afterDragEnter) {

                this.afterDragEnter(target, e, id);
            }
        }
    },


    beforeDragEnter: function (target, e, id) {
        return true;
    },


    alignElWithMouse: function () {
        Ext.dd.DragSource.superclass.alignElWithMouse.apply(this, arguments);
        this.proxy.sync();
    },


    onDragOver: function (e, id) {
        var target = this.cachedTarget || Ext.dd.DragDropMgr.getDDById(id);
        if (this.beforeDragOver(target, e, id) !== false) {
            if (target.isNotifyTarget) {
                var status = target.notifyOver(this, e, this.dragData);
                this.proxy.setStatus(status);
            }

            if (this.afterDragOver) {

                this.afterDragOver(target, e, id);
            }
        }
    },


    beforeDragOver: function (target, e, id) {
        return true;
    },


    onDragOut: function (e, id) {
        var target = this.cachedTarget || Ext.dd.DragDropMgr.getDDById(id);
        if (this.beforeDragOut(target, e, id) !== false) {
            if (target.isNotifyTarget) {
                target.notifyOut(this, e, this.dragData);
            }
            this.proxy.reset();
            if (this.afterDragOut) {

                this.afterDragOut(target, e, id);
            }
        }
        this.cachedTarget = null;
    },


    beforeDragOut: function (target, e, id) {
        return true;
    },


    onDragDrop: function (e, id) {
        var target = this.cachedTarget || Ext.dd.DragDropMgr.getDDById(id);
        if (this.beforeDragDrop(target, e, id) !== false) {
            if (target.isNotifyTarget) {
                if (target.notifyDrop(this, e, this.dragData)) {
                    this.onValidDrop(target, e, id);
                } else {
                    this.onInvalidDrop(target, e, id);
                }
            } else {
                this.onValidDrop(target, e, id);
            }

            if (this.afterDragDrop) {

                this.afterDragDrop(target, e, id);
            }
        }
        delete this.cachedTarget;
    },


    beforeDragDrop: function (target, e, id) {
        return true;
    },


    onValidDrop: function (target, e, id) {
        this.hideProxy();
        if (this.afterValidDrop) {

            this.afterValidDrop(target, e, id);
        }
    },


    getRepairXY: function (e, data) {
        return this.el.getXY();
    },


    onInvalidDrop: function (target, e, id) {
        this.beforeInvalidDrop(target, e, id);
        if (this.cachedTarget) {
            if (this.cachedTarget.isNotifyTarget) {
                this.cachedTarget.notifyOut(this, e, this.dragData);
            }
            this.cacheTarget = null;
        }
        this.proxy.repair(this.getRepairXY(e, this.dragData), this.afterRepair, this);

        if (this.afterInvalidDrop) {

            this.afterInvalidDrop(e, id);
        }
    },


    afterRepair: function () {
        if (Ext.enableFx) {
            this.el.highlight(this.hlColor || "c3daf9");
        }
        this.dragging = false;
    },


    beforeInvalidDrop: function (target, e, id) {
        return true;
    },


    handleMouseDown: function (e) {
        if (this.dragging) {
            return;
        }
        var data = this.getDragData(e);
        if (data && this.onBeforeDrag(data, e) !== false) {
            this.dragData = data;
            this.proxy.stop();
            Ext.dd.DragSource.superclass.handleMouseDown.apply(this, arguments);
        }
    },


    onBeforeDrag: function (data, e) {
        return true;
    },


    onStartDrag: Ext.emptyFn,


    startDrag: function (x, y) {
        this.proxy.reset();
        this.dragging = true;
        this.proxy.update("");
        this.onInitDrag(x, y);
        this.proxy.show();
    },


    onInitDrag: function (x, y) {
        var clone = this.el.dom.cloneNode(true);
        clone.id = Ext.id();
        this.proxy.update(clone);
        this.onStartDrag(x, y);
        return true;
    },


    getProxy: function () {
        return this.proxy;
    },


    hideProxy: function () {
        this.proxy.hide();
        this.proxy.reset(true);
        this.dragging = false;
    },


    triggerCacheRefresh: function () {
        Ext.dd.DDM.refreshCache(this.groups);
    },


    b4EndDrag: function (e) {
    },


    endDrag: function (e) {
        this.onEndDrag(this.dragData, e);
    },


    onEndDrag: function (data, e) {
    },


    autoOffset: function (x, y) {
        this.setDelta(-12, -20);
    },

    destroy: function () {
        Ext.dd.DragSource.superclass.destroy.call(this);
        Ext.destroy(this.proxy);
    }
});
Ext.dd.DropTarget = Ext.extend(Ext.dd.DDTarget, {

    constructor: function (el, config) {
        this.el = Ext.get(el);

        Ext.apply(this, config);

        if (this.containerScroll) {
            Ext.dd.ScrollManager.register(this.el);
        }

        Ext.dd.DropTarget.superclass.constructor.call(this, this.el.dom, this.ddGroup || this.group,
              { isTarget: true });
    },




    dropAllowed: "x-dd-drop-ok",

    dropNotAllowed: "x-dd-drop-nodrop",


    isTarget: true,


    isNotifyTarget: true,


    notifyEnter: function (dd, e, data) {
        if (this.overClass) {
            this.el.addClass(this.overClass);
        }
        return this.dropAllowed;
    },


    notifyOver: function (dd, e, data) {
        return this.dropAllowed;
    },


    notifyOut: function (dd, e, data) {
        if (this.overClass) {
            this.el.removeClass(this.overClass);
        }
    },


    notifyDrop: function (dd, e, data) {
        return false;
    },

    destroy: function () {
        Ext.dd.DropTarget.superclass.destroy.call(this);
        if (this.containerScroll) {
            Ext.dd.ScrollManager.unregister(this.el);
        }
    }
});
Ext.dd.DragZone = Ext.extend(Ext.dd.DragSource, {

    constructor: function (el, config) {
        Ext.dd.DragZone.superclass.constructor.call(this, el, config);
        if (this.containerScroll) {
            Ext.dd.ScrollManager.register(this.el);
        }
    },






    getDragData: function (e) {
        return Ext.dd.Registry.getHandleFromEvent(e);
    },


    onInitDrag: function (x, y) {
        this.proxy.update(this.dragData.ddel.cloneNode(true));
        this.onStartDrag(x, y);
        return true;
    },


    afterRepair: function () {
        if (Ext.enableFx) {
            Ext.Element.fly(this.dragData.ddel).highlight(this.hlColor || "c3daf9");
        }
        this.dragging = false;
    },


    getRepairXY: function (e) {
        return Ext.Element.fly(this.dragData.ddel).getXY();
    },

    destroy: function () {
        Ext.dd.DragZone.superclass.destroy.call(this);
        if (this.containerScroll) {
            Ext.dd.ScrollManager.unregister(this.el);
        }
    }
});
Ext.dd.DropZone = function (el, config) {
    Ext.dd.DropZone.superclass.constructor.call(this, el, config);
};

Ext.extend(Ext.dd.DropZone, Ext.dd.DropTarget, {

    getTargetFromEvent: function (e) {
        return Ext.dd.Registry.getTargetFromEvent(e);
    },


    onNodeEnter: function (n, dd, e, data) {

    },


    onNodeOver: function (n, dd, e, data) {
        return this.dropAllowed;
    },


    onNodeOut: function (n, dd, e, data) {

    },


    onNodeDrop: function (n, dd, e, data) {
        return false;
    },


    onContainerOver: function (dd, e, data) {
        return this.dropNotAllowed;
    },


    onContainerDrop: function (dd, e, data) {
        return false;
    },


    notifyEnter: function (dd, e, data) {
        return this.dropNotAllowed;
    },


    notifyOver: function (dd, e, data) {
        var n = this.getTargetFromEvent(e);
        if (!n) {
            if (this.lastOverNode) {
                this.onNodeOut(this.lastOverNode, dd, e, data);
                this.lastOverNode = null;
            }
            return this.onContainerOver(dd, e, data);
        }
        if (this.lastOverNode != n) {
            if (this.lastOverNode) {
                this.onNodeOut(this.lastOverNode, dd, e, data);
            }
            this.onNodeEnter(n, dd, e, data);
            this.lastOverNode = n;
        }
        return this.onNodeOver(n, dd, e, data);
    },


    notifyOut: function (dd, e, data) {
        if (this.lastOverNode) {
            this.onNodeOut(this.lastOverNode, dd, e, data);
            this.lastOverNode = null;
        }
    },


    notifyDrop: function (dd, e, data) {
        if (this.lastOverNode) {
            this.onNodeOut(this.lastOverNode, dd, e, data);
            this.lastOverNode = null;
        }
        var n = this.getTargetFromEvent(e);
        return n ?
            this.onNodeDrop(n, dd, e, data) :
            this.onContainerDrop(dd, e, data);
    },


    triggerCacheRefresh: function () {
        Ext.dd.DDM.refreshCache(this.groups);
    }
});
Ext.Element.addMethods({

    initDD: function (group, config, overrides) {
        var dd = new Ext.dd.DD(Ext.id(this.dom), group, config);
        return Ext.apply(dd, overrides);
    },


    initDDProxy: function (group, config, overrides) {
        var dd = new Ext.dd.DDProxy(Ext.id(this.dom), group, config);
        return Ext.apply(dd, overrides);
    },


    initDDTarget: function (group, config, overrides) {
        var dd = new Ext.dd.DDTarget(Ext.id(this.dom), group, config);
        return Ext.apply(dd, overrides);
    }
});

Ext.data.Api = (function () {





    var validActions = {};

    return {

        actions: {
            create: 'create',
            read: 'read',
            update: 'update',
            destroy: 'destroy'
        },


        restActions: {
            create: 'POST',
            read: 'GET',
            update: 'PUT',
            destroy: 'DELETE'
        },


        isAction: function (action) {
            return (Ext.data.Api.actions[action]) ? true : false;
        },


        getVerb: function (name) {
            if (validActions[name]) {
                return validActions[name];
            }
            for (var verb in this.actions) {
                if (this.actions[verb] === name) {
                    validActions[name] = verb;
                    break;
                }
            }
            return (validActions[name] !== undefined) ? validActions[name] : null;
        },


        isValid: function (api) {
            var invalid = [];
            var crud = this.actions;
            for (var action in api) {
                if (!(action in crud)) {
                    invalid.push(action);
                }
            }
            return (!invalid.length) ? true : invalid;
        },


        hasUniqueUrl: function (proxy, verb) {
            var url = (proxy.api[verb]) ? proxy.api[verb].url : null;
            var unique = true;
            for (var action in proxy.api) {
                if ((unique = (action === verb) ? true : (proxy.api[action].url != url) ? true : false) === false) {
                    break;
                }
            }
            return unique;
        },


        prepare: function (proxy) {
            if (!proxy.api) {
                proxy.api = {};
            }
            for (var verb in this.actions) {
                var action = this.actions[verb];
                proxy.api[action] = proxy.api[action] || proxy.url || proxy.directFn;
                if (typeof (proxy.api[action]) == 'string') {
                    proxy.api[action] = {
                        url: proxy.api[action],
                        method: (proxy.restful === true) ? Ext.data.Api.restActions[action] : undefined
                    };
                }
            }
        },


        restify: function (proxy) {
            proxy.restful = true;
            for (var verb in this.restActions) {
                proxy.api[this.actions[verb]].method ||
                    (proxy.api[this.actions[verb]].method = this.restActions[verb]);
            }


            proxy.onWrite = proxy.onWrite.createInterceptor(function (action, o, response, rs) {
                var reader = o.reader;
                var res = new Ext.data.Response({
                    action: action,
                    raw: response
                });

                switch (response.status) {
                    case 200:
                        return true;
                        break;
                    case 201:
                        if (Ext.isEmpty(res.raw.responseText)) {
                            res.success = true;
                        } else {

                            return true;
                        }
                        break;
                    case 204:
                        res.success = true;
                        res.data = null;
                        break;
                    default:
                        return true;
                        break;
                }
                if (res.success === true) {
                    this.fireEvent("write", this, action, res.data, res, rs, o.request.arg);
                } else {
                    this.fireEvent('exception', this, 'remote', action, o, res, rs);
                }
                o.request.callback.call(o.request.scope, res.data, res, res.success);

                return false;
            }, proxy);
        }
    };
})();


Ext.data.Response = function (params, response) {
    Ext.apply(this, params, {
        raw: response
    });
};
Ext.data.Response.prototype = {
    message: null,
    success: false,
    status: null,
    root: null,
    raw: null,

    getMessage: function () {
        return this.message;
    },
    getSuccess: function () {
        return this.success;
    },
    getStatus: function () {
        return this.status;
    },
    getRoot: function () {
        return this.root;
    },
    getRawResponse: function () {
        return this.raw;
    }
};


Ext.data.Api.Error = Ext.extend(Ext.Error, {
    constructor: function (message, arg) {
        this.arg = arg;
        Ext.Error.call(this, message);
    },
    name: 'Ext.data.Api'
});
Ext.apply(Ext.data.Api.Error.prototype, {
    lang: {
        'action-url-undefined': 'No fallback url defined for this action.  When defining a DataProxy api, please be sure to define an url for each CRUD action in Ext.data.Api.actions or define a default url in addition to your api-configuration.',
        'invalid': 'received an invalid API-configuration.  Please ensure your proxy API-configuration contains only the actions defined in Ext.data.Api.actions',
        'invalid-url': 'Invalid url.  Please review your proxy configuration.',
        'execute': 'Attempted to execute an unknown action.  Valid API actions are defined in Ext.data.Api.actions"'
    }
});




Ext.data.SortTypes = {

    none: function (s) {
        return s;
    },


    stripTagsRE: /<\/?[^>]+>/gi,


    asText: function (s) {
        return String(s).replace(this.stripTagsRE, "");
    },


    asUCText: function (s) {
        return String(s).toUpperCase().replace(this.stripTagsRE, "");
    },


    asUCString: function (s) {
        return String(s).toUpperCase();
    },


    asDate: function (s) {
        if (!s) {
            return 0;
        }
        if (Ext.isDate(s)) {
            return s.getTime();
        }
        return Date.parse(String(s));
    },


    asFloat: function (s) {
        var val = parseFloat(String(s).replace(/,/g, ""));
        return isNaN(val) ? 0 : val;
    },


    asInt: function (s) {
        var val = parseInt(String(s).replace(/,/g, ""), 10);
        return isNaN(val) ? 0 : val;
    }
};
Ext.data.Record = function (data, id) {

    this.id = (id || id === 0) ? id : Ext.data.Record.id(this);
    this.data = data || {};
};


Ext.data.Record.create = function (o) {
    var f = Ext.extend(Ext.data.Record, {});
    var p = f.prototype;
    p.fields = new Ext.util.MixedCollection(false, function (field) {
        return field.name;
    });
    for (var i = 0, len = o.length; i < len; i++) {
        p.fields.add(new Ext.data.Field(o[i]));
    }
    f.getField = function (name) {
        return p.fields.get(name);
    };
    return f;
};

Ext.data.Record.PREFIX = 'ext-record';
Ext.data.Record.AUTO_ID = 1;
Ext.data.Record.EDIT = 'edit';
Ext.data.Record.REJECT = 'reject';
Ext.data.Record.COMMIT = 'commit';



Ext.data.Record.id = function (rec) {
    rec.phantom = true;
    return [Ext.data.Record.PREFIX, '-', Ext.data.Record.AUTO_ID++].join('');
};

Ext.data.Record.prototype = {






    dirty: false,
    editing: false,
    error: null,

    modified: null,

    phantom: false,


    join: function (store) {

        this.store = store;
    },


    set: function (name, value) {
        var encode = Ext.isPrimitive(value) ? String : Ext.encode;
        if (encode(this.data[name]) == encode(value)) {
            return;
        }
        this.dirty = true;
        if (!this.modified) {
            this.modified = {};
        }
        if (this.modified[name] === undefined) {
            this.modified[name] = this.data[name];
        }
        this.data[name] = value;
        if (!this.editing) {
            this.afterEdit();
        }
    },


    afterEdit: function () {
        if (this.store != undefined && typeof this.store.afterEdit == "function") {
            this.store.afterEdit(this);
        }
    },


    afterReject: function () {
        if (this.store) {
            this.store.afterReject(this);
        }
    },


    afterCommit: function () {
        if (this.store) {
            this.store.afterCommit(this);
        }
    },


    get: function (name) {
        return this.data[name];
    },


    beginEdit: function () {
        this.editing = true;
        this.modified = this.modified || {};
    },


    cancelEdit: function () {
        this.editing = false;
        delete this.modified;
    },


    endEdit: function () {
        this.editing = false;
        if (this.dirty) {
            this.afterEdit();
        }
    },


    reject: function (silent) {
        var m = this.modified;
        for (var n in m) {
            if (typeof m[n] != "function") {
                this.data[n] = m[n];
            }
        }
        this.dirty = false;
        delete this.modified;
        this.editing = false;
        if (silent !== true) {
            this.afterReject();
        }
    },


    commit: function (silent) {
        this.dirty = false;
        delete this.modified;
        this.editing = false;
        if (silent !== true) {
            this.afterCommit();
        }
    },


    getChanges: function () {
        var m = this.modified, cs = {};
        for (var n in m) {
            if (m.hasOwnProperty(n)) {
                cs[n] = this.data[n];
            }
        }
        return cs;
    },


    hasError: function () {
        return this.error !== null;
    },


    clearError: function () {
        this.error = null;
    },


    copy: function (newId) {
        return new this.constructor(Ext.apply({}, this.data), newId || this.id);
    },


    isModified: function (fieldName) {
        return !!(this.modified && this.modified.hasOwnProperty(fieldName));
    },


    isValid: function () {
        return this.fields.find(function (f) {
            return (f.allowBlank === false && Ext.isEmpty(this.data[f.name])) ? true : false;
        }, this) ? false : true;
    },


    markDirty: function () {
        this.dirty = true;
        if (!this.modified) {
            this.modified = {};
        }
        this.fields.each(function (f) {
            this.modified[f.name] = this.data[f.name];
        }, this);
    }
};

Ext.StoreMgr = Ext.apply(new Ext.util.MixedCollection(), {



    register: function () {
        for (var i = 0, s; (s = arguments[i]); i++) {
            this.add(s);
        }
    },


    unregister: function () {
        for (var i = 0, s; (s = arguments[i]); i++) {
            this.remove(this.lookup(s));
        }
    },


    lookup: function (id) {
        if (Ext.isArray(id)) {
            var fields = ['field1'], expand = !Ext.isArray(id[0]);
            if (!expand) {
                for (var i = 2, len = id[0].length; i <= len; ++i) {
                    fields.push('field' + i);
                }
            }
            return new Ext.data.ArrayStore({
                fields: fields,
                data: id,
                expandData: expand,
                autoDestroy: true,
                autoCreated: true

            });
        }
        return Ext.isObject(id) ? (id.events ? id : Ext.create(id, 'store')) : this.get(id);
    },


    getKey: function (o) {
        return o.storeId;
    }
});
Ext.data.Store = Ext.extend(Ext.util.Observable, {







    writer: undefined,



    remoteSort: false,


    autoDestroy: false,


    pruneModifiedRecords: false,


    lastOptions: null,


    autoSave: true,


    batch: true,


    restful: false,


    paramNames: undefined,


    defaultParamNames: {
        start: 'start',
        limit: 'limit',
        sort: 'sort',
        dir: 'dir'
    },

    isDestroyed: false,
    hasMultiSort: false,


    batchKey: '_ext_batch_',

    constructor: function (config) {




        this.data = new Ext.util.MixedCollection(false);
        this.data.getKey = function (o) {
            return o.id;
        };



        this.removed = [];

        if (config && config.data) {
            this.inlineData = config.data;
            delete config.data;
        }

        Ext.apply(this, config);


        this.baseParams = Ext.isObject(this.baseParams) ? this.baseParams : {};

        this.paramNames = Ext.applyIf(this.paramNames || {}, this.defaultParamNames);

        if ((this.url || this.api) && !this.proxy) {
            this.proxy = new Ext.data.HttpProxy({ url: this.url, api: this.api });
        }

        if (this.restful === true && this.proxy) {


            this.batch = false;
            Ext.data.Api.restify(this.proxy);
        }

        if (this.reader) {
            if (!this.recordType) {
                this.recordType = this.reader.recordType;
            }
            if (this.reader.onMetaChange) {
                this.reader.onMetaChange = this.reader.onMetaChange.createSequence(this.onMetaChange, this);
            }
            if (this.writer) {
                if (this.writer instanceof (Ext.data.DataWriter) === false) {
                    this.writer = this.buildWriter(this.writer);
                }
                this.writer.meta = this.reader.meta;
                this.pruneModifiedRecords = true;
            }
        }



        if (this.recordType) {

            this.fields = this.recordType.prototype.fields;
        }
        this.modified = [];

        this.addEvents(

            'datachanged',

            'metachange',

            'add',

            'remove',

            'update',

            'clear',

            'exception',

            'beforeload',

            'load',

            'loadexception',

            'beforewrite',

            'write',

            'beforesave',

            'save'

        );

        if (this.proxy) {

            this.relayEvents(this.proxy, ['loadexception', 'exception']);
        }

        if (this.writer) {
            this.on({
                scope: this,
                add: this.createRecords,
                remove: this.destroyRecord,
                update: this.updateRecord,
                clear: this.onClear
            });
        }

        this.sortToggle = {};
        if (this.sortField) {
            this.setDefaultSort(this.sortField, this.sortDir);
        } else if (this.sortInfo) {
            this.setDefaultSort(this.sortInfo.field, this.sortInfo.direction);
        }

        Ext.data.Store.superclass.constructor.call(this);

        if (this.id) {
            this.storeId = this.id;
            delete this.id;
        }
        if (this.storeId) {
            Ext.StoreMgr.register(this);
        }
        if (this.inlineData) {
            this.loadData(this.inlineData);
            delete this.inlineData;
        } else if (this.autoLoad) {
            this.load.defer(10, this, [
                typeof this.autoLoad == 'object' ?
                    this.autoLoad : undefined]);
        }

        this.batchCounter = 0;
        this.batches = {};
    },


    buildWriter: function (config) {
        var klass = undefined,
            type = (config.format || 'json').toLowerCase();
        switch (type) {
            case 'json':
                klass = Ext.data.JsonWriter;
                break;
            case 'xml':
                klass = Ext.data.XmlWriter;
                break;
            default:
                klass = Ext.data.JsonWriter;
        }
        return new klass(config);
    },


    destroy: function () {
        if (!this.isDestroyed) {
            if (this.storeId) {
                Ext.StoreMgr.unregister(this);
            }
            this.clearData();
            this.data = null;
            Ext.destroy(this.proxy);
            this.reader = this.writer = null;
            this.purgeListeners();
            this.isDestroyed = true;
        }
    },


    add: function (records) {
        var i, record, index;

        records = [].concat(records);
        if (records.length < 1) {
            return;
        }

        for (i = 0, len = records.length; i < len; i++) {
            record = records[i];

            record.join(this);

            if (record.dirty || record.phantom) {
                this.modified.push(record);
            }
        }

        index = this.data.length;
        this.data.addAll(records);

        if (this.snapshot) {
            this.snapshot.addAll(records);
        }

        this.fireEvent('add', this, records, index);
    },


    addSorted: function (record) {
        var index = this.findInsertIndex(record);
        this.insert(index, record);
    },


    doUpdate: function (rec) {
        this.data.replace(rec.id, rec);
        if (this.snapshot) {
            this.snapshot.replace(rec.id, rec);
        }
        this.fireEvent('update', this, rec, Ext.data.Record.COMMIT);
    },


    remove: function (record) {
        if (Ext.isArray(record)) {
            Ext.each(record, function (r) {
                this.remove(r);
            }, this);
            return;
        }
        var index = this.data.indexOf(record);
        if (index > -1) {
            record.join(null);
            this.data.removeAt(index);
        }
        if (this.pruneModifiedRecords) {
            this.modified.remove(record);
        }
        if (this.snapshot) {
            this.snapshot.remove(record);
        }
        if (index > -1) {
            this.fireEvent('remove', this, record, index);
        }
    },


    removeAt: function (index) {
        this.remove(this.getAt(index));
    },


    removeAll: function (silent) {
        var items = [];
        this.each(function (rec) {
            items.push(rec);
        });
        this.clearData();
        if (this.snapshot) {
            this.snapshot.clear();
        }
        if (this.pruneModifiedRecords) {
            this.modified = [];
        }
        if (silent !== true) {
            this.fireEvent('clear', this, items);
        }
    },


    onClear: function (store, records) {
        Ext.each(records, function (rec, index) {
            this.destroyRecord(this, rec, index);
        }, this);
    },


    insert: function (index, records) {
        var i, record;

        records = [].concat(records);
        for (i = 0, len = records.length; i < len; i++) {
            record = records[i];

            this.data.insert(index + i, record);
            record.join(this);

            if (record.dirty || record.phantom) {
                this.modified.push(record);
            }
        }

        if (this.snapshot) {
            this.snapshot.addAll(records);
        }

        this.fireEvent('add', this, records, index);
    },


    indexOf: function (record) {
        return this.data.indexOf(record);
    },


    indexOfId: function (id) {
        return this.data.indexOfKey(id);
    },


    getById: function (id) {
        return (this.snapshot || this.data).key(id);
    },


    getAt: function (index) {
        return this.data.itemAt(index);
    },


    getRange: function (start, end) {
        return this.data.getRange(start, end);
    },


    storeOptions: function (o) {
        o = Ext.apply({}, o);
        delete o.callback;
        delete o.scope;
        this.lastOptions = o;
    },


    clearData: function () {
        this.data.each(function (rec) {
            rec.join(null);
        });
        this.data.clear();
    },


    load: function (options) {
        options = Ext.apply({}, options);
        this.storeOptions(options);
        if (this.sortInfo && this.remoteSort) {
            var pn = this.paramNames;
            options.params = Ext.apply({}, options.params);
            options.params[pn.sort] = this.sortInfo.field;
            options.params[pn.dir] = this.sortInfo.direction;
        }
        try {
            return this.execute('read', null, options);
        } catch (e) {
            this.handleException(e);
            return false;
        }
    },


    updateRecord: function (store, record, action) {
        if (action == Ext.data.Record.EDIT && this.autoSave === true && (!record.phantom || (record.phantom && record.isValid()))) {
            this.save();
        }
    },


    createRecords: function (store, records, index) {
        var modified = this.modified,
            length = records.length,
            record, i;

        for (i = 0; i < length; i++) {
            record = records[i];

            if (record.phantom && record.isValid()) {
                record.markDirty();

                if (modified.indexOf(record) == -1) {
                    modified.push(record);
                }
            }
        }
        if (this.autoSave === true) {
            this.save();
        }
    },


    destroyRecord: function (store, record, index) {
        if (this.modified.indexOf(record) != -1) {
            this.modified.remove(record);
        }
        if (!record.phantom) {
            this.removed.push(record);




            record.lastIndex = index;

            if (this.autoSave === true) {
                this.save();
            }
        }
    },


    execute: function (action, rs, options, batch) {

        if (!Ext.data.Api.isAction(action)) {
            throw new Ext.data.Api.Error('execute', action);
        }

        options = Ext.applyIf(options || {}, {
            params: {}
        });
        if (batch !== undefined) {
            this.addToBatch(batch);
        }


        var doRequest = true;

        if (action === 'read') {
            doRequest = this.fireEvent('beforeload', this, options);
            Ext.applyIf(options.params, this.baseParams);
        }
        else {


            if (this.writer.listful === true && this.restful !== true) {
                rs = (Ext.isArray(rs)) ? rs : [rs];
            }

            else if (Ext.isArray(rs) && rs.length == 1) {
                rs = rs.shift();
            }

            if ((doRequest = this.fireEvent('beforewrite', this, action, rs, options)) !== false) {
                this.writer.apply(options.params, this.baseParams, action, rs);
            }
        }
        if (doRequest !== false) {

            if (this.writer && this.proxy.url && !this.proxy.restful && !Ext.data.Api.hasUniqueUrl(this.proxy, action)) {
                options.params.xaction = action;
            }





            this.proxy.request(Ext.data.Api.actions[action], rs, options.params, this.reader, this.createCallback(action, rs, batch), this, options);
        }
        return doRequest;
    },


    save: function () {
        if (!this.writer) {
            throw new Ext.data.Store.Error('writer-undefined');
        }

        var queue = [],
            len,
            trans,
            batch,
            data = {},
            i;

        if (this.removed.length) {
            queue.push(['destroy', this.removed]);
        }


        var rs = [].concat(this.getModifiedRecords());
        if (rs.length) {

            var phantoms = [];
            for (i = rs.length - 1; i >= 0; i--) {
                if (rs[i].phantom === true) {
                    var rec = rs.splice(i, 1).shift();
                    if (rec.isValid()) {
                        phantoms.push(rec);
                    }
                } else if (!rs[i].isValid()) {
                    rs.splice(i, 1);
                }
            }

            if (phantoms.length) {
                queue.push(['create', phantoms]);
            }


            if (rs.length) {
                queue.push(['update', rs]);
            }
        }
        len = queue.length;
        if (len) {
            batch = ++this.batchCounter;
            for (i = 0; i < len; ++i) {
                trans = queue[i];
                data[trans[0]] = trans[1];
            }
            if (this.fireEvent('beforesave', this, data) !== false) {
                for (i = 0; i < len; ++i) {
                    trans = queue[i];
                    this.doTransaction(trans[0], trans[1], batch);
                }
                return batch;
            }
        }
        return -1;
    },


    doTransaction: function (action, rs, batch) {
        function transaction(records) {
            try {
                this.execute(action, records, undefined, batch);
            } catch (e) {
                this.handleException(e);
            }
        }
        if (this.batch === false) {
            for (var i = 0, len = rs.length; i < len; i++) {
                transaction.call(this, rs[i]);
            }
        } else {
            transaction.call(this, rs);
        }
    },


    addToBatch: function (batch) {
        var b = this.batches,
            key = this.batchKey + batch,
            o = b[key];

        if (!o) {
            b[key] = o = {
                id: batch,
                count: 0,
                data: {}
            };
        }
        ++o.count;
    },

    removeFromBatch: function (batch, action, data) {
        var b = this.batches,
            key = this.batchKey + batch,
            o = b[key],
            arr;


        if (o) {
            arr = o.data[action] || [];
            o.data[action] = arr.concat(data);
            if (o.count === 1) {
                data = o.data;
                delete b[key];
                this.fireEvent('save', this, batch, data);
            } else {
                --o.count;
            }
        }
    },



    createCallback: function (action, rs, batch) {
        var actions = Ext.data.Api.actions;
        return (action == 'read') ? this.loadRecords : function (data, response, success) {

            this['on' + Ext.util.Format.capitalize(action) + 'Records'](success, rs, [].concat(data));

            if (success === true) {
                this.fireEvent('write', this, action, data, response, rs);
            }
            this.removeFromBatch(batch, action, data);
        };
    },




    clearModified: function (rs) {
        if (Ext.isArray(rs)) {
            for (var n = rs.length - 1; n >= 0; n--) {
                this.modified.splice(this.modified.indexOf(rs[n]), 1);
            }
        } else {
            this.modified.splice(this.modified.indexOf(rs), 1);
        }
    },


    reMap: function (record) {
        if (Ext.isArray(record)) {
            for (var i = 0, len = record.length; i < len; i++) {
                this.reMap(record[i]);
            }
        } else {
            delete this.data.map[record._phid];
            this.data.map[record.id] = record;
            var index = this.data.keys.indexOf(record._phid);
            this.data.keys.splice(index, 1, record.id);
            delete record._phid;
        }
    },


    onCreateRecords: function (success, rs, data) {
        if (success === true) {
            try {
                this.reader.realize(rs, data);
                this.reMap(rs);
            }
            catch (e) {
                this.handleException(e);
                if (Ext.isArray(rs)) {

                    this.onCreateRecords(success, rs, data);
                }
            }
        }
    },


    onUpdateRecords: function (success, rs, data) {
        if (success === true) {
            try {
                this.reader.update(rs, data);
            } catch (e) {
                this.handleException(e);
                if (Ext.isArray(rs)) {

                    this.onUpdateRecords(success, rs, data);
                }
            }
        }
    },


    onDestroyRecords: function (success, rs, data) {

        rs = (rs instanceof Ext.data.Record) ? [rs] : [].concat(rs);
        for (var i = 0, len = rs.length; i < len; i++) {
            this.removed.splice(this.removed.indexOf(rs[i]), 1);
        }
        if (success === false) {


            for (i = rs.length - 1; i >= 0; i--) {
                this.insert(rs[i].lastIndex, rs[i]);
            }
        }
    },


    handleException: function (e) {

        Ext.handleError(e);
    },


    reload: function (options) {
        this.load(Ext.applyIf(options || {}, this.lastOptions));
    },



    loadRecords: function (o, options, success) {
        var i;

        if (this.isDestroyed === true) {
            return;
        }
        if (!o || success === false) {
            if (success !== false) {
                this.fireEvent('load', this, [], options);
            }
            if (options.callback) {
                options.callback.call(options.scope || this, [], options, false, o);
            }
            return;
        }
        var r = o.records, t = o.totalRecords || r.length;
        if (!options || options.add !== true) {
            if (this.pruneModifiedRecords) {
                this.modified = [];
            }
            for (i = 0, len = r.length; i < len; i++) {
                r[i].join(this);
            }
            if (this.snapshot) {
                this.data = this.snapshot;
                delete this.snapshot;
            }
            this.clearData();
            this.data.addAll(r);
            this.totalLength = t;
            this.applySort();
            this.fireEvent('datachanged', this);
        } else {
            var toAdd = [],
                rec,
                cnt = 0;
            for (i = 0, len = r.length; i < len; ++i) {
                rec = r[i];
                if (this.indexOfId(rec.id) > -1) {
                    this.doUpdate(rec);
                } else {
                    toAdd.push(rec);
                    ++cnt;
                }
            }
            this.totalLength = Math.max(t, this.data.length + cnt);
            this.add(toAdd);
        }
        this.fireEvent('load', this, r, options);
        if (options.callback) {
            options.callback.call(options.scope || this, r, options, true);
        }
    },


    loadData: function (o, append) {
        var r = this.reader.readRecords(o);
        this.loadRecords(r, { add: append }, true);
    },


    getCount: function () {
        return this.data.length || 0;
    },


    getTotalCount: function () {
        return this.totalLength || 0;
    },


    getSortState: function () {
        return this.sortInfo;
    },


    applySort: function () {
        if ((this.sortInfo || this.multiSortInfo) && !this.remoteSort) {
            this.sortData();
        }
    },


    sortData: function () {
        var sortInfo = this.hasMultiSort ? this.multiSortInfo : this.sortInfo,
            direction = sortInfo.direction || "ASC",
            sorters = sortInfo.sorters,
            sortFns = [];


        if (!this.hasMultiSort) {
            sorters = [{ direction: direction, field: sortInfo.field}];
        }


        for (var i = 0, j = sorters.length; i < j; i++) {
            sortFns.push(this.createSortFunction(sorters[i].field, sorters[i].direction));
        }

        if (sortFns.length == 0) {
            return;
        }



        var directionModifier = direction.toUpperCase() == "DESC" ? -1 : 1;


        var fn = function (r1, r2) {
            var result = sortFns[0].call(this, r1, r2);


            if (sortFns.length > 1) {
                for (var i = 1, j = sortFns.length; i < j; i++) {
                    result = result || sortFns[i].call(this, r1, r2);
                }
            }

            return directionModifier * result;
        };


        this.data.sort(direction, fn);
        if (this.snapshot && this.snapshot != this.data) {
            this.snapshot.sort(direction, fn);
        }
    },


    createSortFunction: function (field, direction) {
        direction = direction || "ASC";
        var directionModifier = direction.toUpperCase() == "DESC" ? -1 : 1;

        var sortType = this.fields.get(field).sortType;



        return function (r1, r2) {
            var v1 = sortType(r1.data[field]),
                v2 = sortType(r2.data[field]);

            return directionModifier * (v1 > v2 ? 1 : (v1 < v2 ? -1 : 0));
        };
    },


    setDefaultSort: function (field, dir) {
        dir = dir ? dir.toUpperCase() : 'ASC';
        this.sortInfo = { field: field, direction: dir };
        this.sortToggle[field] = dir;
    },


    sort: function (fieldName, dir) {
        if (Ext.isArray(arguments[0])) {
            return this.multiSort.call(this, fieldName, dir);
        } else {
            return this.singleSort(fieldName, dir);
        }
    },


    singleSort: function (fieldName, dir) {
        var field = this.fields.get(fieldName);
        if (!field) {
            return false;
        }

        var name = field.name,
            sortInfo = this.sortInfo || null,
            sortToggle = this.sortToggle ? this.sortToggle[name] : null;

        if (!dir) {
            if (sortInfo && sortInfo.field == name) {
                dir = (this.sortToggle[name] || 'ASC').toggle('ASC', 'DESC');
            } else {
                dir = field.sortDir;
            }
        }

        this.sortToggle[name] = dir;
        this.sortInfo = { field: name, direction: dir };
        this.hasMultiSort = false;

        if (this.remoteSort) {
            if (!this.load(this.lastOptions)) {
                if (sortToggle) {
                    this.sortToggle[name] = sortToggle;
                }
                if (sortInfo) {
                    this.sortInfo = sortInfo;
                }
            }
        } else {
            this.applySort();
            this.fireEvent('datachanged', this);
        }
        return true;
    },


    multiSort: function (sorters, direction) {
        this.hasMultiSort = true;
        direction = direction || "ASC";


        if (this.multiSortInfo && direction == this.multiSortInfo.direction) {
            direction = direction.toggle("ASC", "DESC");
        }


        this.multiSortInfo = {
            sorters: sorters,
            direction: direction
        };

        if (this.remoteSort) {
            this.singleSort(sorters[0].field, sorters[0].direction);

        } else {
            this.applySort();
            this.fireEvent('datachanged', this);
        }
    },


    each: function (fn, scope) {
        this.data.each(fn, scope);
    },


    getModifiedRecords: function () {
        return this.modified;
    },


    sum: function (property, start, end) {
        var rs = this.data.items, v = 0;
        start = start || 0;
        end = (end || end === 0) ? end : rs.length - 1;

        for (var i = start; i <= end; i++) {
            v += (rs[i].data[property] || 0);
        }
        return v;
    },


    createFilterFn: function (property, value, anyMatch, caseSensitive, exactMatch) {
        if (Ext.isEmpty(value, false)) {
            return false;
        }
        value = this.data.createValueMatcher(value, anyMatch, caseSensitive, exactMatch);
        return function (r) {
            return value.test(r.data[property]);
        };
    },


    createMultipleFilterFn: function (filters) {
        return function (record) {
            var isMatch = true;

            for (var i = 0, j = filters.length; i < j; i++) {
                var filter = filters[i],
                    fn = filter.fn,
                    scope = filter.scope;

                isMatch = isMatch && fn.call(scope, record);
            }

            return isMatch;
        };
    },


    filter: function (property, value, anyMatch, caseSensitive, exactMatch) {
        var fn;

        if (Ext.isObject(property)) {
            property = [property];
        }

        if (Ext.isArray(property)) {
            var filters = [];


            for (var i = 0, j = property.length; i < j; i++) {
                var filter = property[i],
                    func = filter.fn,
                    scope = filter.scope || this;


                if (!Ext.isFunction(func)) {
                    func = this.createFilterFn(filter.property, filter.value, filter.anyMatch, filter.caseSensitive, filter.exactMatch);
                }

                filters.push({ fn: func, scope: scope });
            }

            fn = this.createMultipleFilterFn(filters);
        } else {

            fn = this.createFilterFn(property, value, anyMatch, caseSensitive, exactMatch);
        }

        return fn ? this.filterBy(fn) : this.clearFilter();
    },


    filterBy: function (fn, scope) {
        this.snapshot = this.snapshot || this.data;
        this.data = this.queryBy(fn, scope || this);
        this.fireEvent('datachanged', this);
    },


    clearFilter: function (suppressEvent) {
        if (this.isFiltered()) {
            this.data = this.snapshot;
            delete this.snapshot;
            if (suppressEvent !== true) {
                this.fireEvent('datachanged', this);
            }
        }
    },


    isFiltered: function () {
        return !!this.snapshot && this.snapshot != this.data;
    },


    query: function (property, value, anyMatch, caseSensitive) {
        var fn = this.createFilterFn(property, value, anyMatch, caseSensitive);
        return fn ? this.queryBy(fn) : this.data.clone();
    },


    queryBy: function (fn, scope) {
        var data = this.snapshot || this.data;
        return data.filterBy(fn, scope || this);
    },


    find: function (property, value, start, anyMatch, caseSensitive) {
        var fn = this.createFilterFn(property, value, anyMatch, caseSensitive);
        return fn ? this.data.findIndexBy(fn, null, start) : -1;
    },


    findExact: function (property, value, start) {
        return this.data.findIndexBy(function (rec) {
            return rec.get(property) === value;
        }, this, start);
    },


    findBy: function (fn, scope, start) {
        return this.data.findIndexBy(fn, scope, start);
    },


    collect: function (dataIndex, allowNull, bypassFilter) {
        var d = (bypassFilter === true && this.snapshot) ?
                this.snapshot.items : this.data.items;
        var v, sv, r = [], l = {};
        for (var i = 0, len = d.length; i < len; i++) {
            v = d[i].data[dataIndex];
            sv = String(v);
            if ((allowNull || !Ext.isEmpty(v)) && !l[sv]) {
                l[sv] = true;
                r[r.length] = v;
            }
        }
        return r;
    },


    afterEdit: function (record) {
        if (this.modified.indexOf(record) == -1) {
            this.modified.push(record);
        }
        this.fireEvent('update', this, record, Ext.data.Record.EDIT);
    },


    afterReject: function (record) {
        this.modified.remove(record);
        this.fireEvent('update', this, record, Ext.data.Record.REJECT);
    },


    afterCommit: function (record) {
        this.modified.remove(record);
        this.fireEvent('update', this, record, Ext.data.Record.COMMIT);
    },


    commitChanges: function () {
        var modified = this.modified.slice(0),
            length = modified.length,
            i;

        for (i = 0; i < length; i++) {
            modified[i].commit();
        }

        this.modified = [];
        this.removed = [];
    },


    rejectChanges: function () {
        var modified = this.modified.slice(0),
            removed = this.removed.slice(0).reverse(),
            mLength = modified.length,
            rLength = removed.length,
            i;

        for (i = 0; i < mLength; i++) {
            modified[i].reject();
        }

        for (i = 0; i < rLength; i++) {
            this.insert(removed[i].lastIndex || 0, removed[i]);
            removed[i].reject();
        }

        this.modified = [];
        this.removed = [];
    },


    onMetaChange: function (meta) {
        this.recordType = this.reader.recordType;
        this.fields = this.recordType.prototype.fields;
        delete this.snapshot;
        if (this.reader.meta.sortInfo) {
            this.sortInfo = this.reader.meta.sortInfo;
        } else if (this.sortInfo && !this.fields.get(this.sortInfo.field)) {
            delete this.sortInfo;
        }
        if (this.writer) {
            this.writer.meta = this.reader.meta;
        }
        this.modified = [];
        this.fireEvent('metachange', this, this.reader.meta);
    },


    findInsertIndex: function (record) {
        this.suspendEvents();
        var data = this.data.clone();
        this.data.add(record);
        this.applySort();
        var index = this.data.indexOf(record);
        this.data = data;
        this.resumeEvents();
        return index;
    },


    setBaseParam: function (name, value) {
        this.baseParams = this.baseParams || {};
        this.baseParams[name] = value;
    }
});

Ext.reg('store', Ext.data.Store);


Ext.data.Store.Error = Ext.extend(Ext.Error, {
    name: 'Ext.data.Store'
});
Ext.apply(Ext.data.Store.Error.prototype, {
    lang: {
        'writer-undefined': 'Attempted to execute a write-action without a DataWriter installed.'
    }
});

Ext.data.Field = Ext.extend(Object, {

    constructor: function (config) {
        if (Ext.isString(config)) {
            config = { name: config };
        }
        Ext.apply(this, config);

        var types = Ext.data.Types,
            st = this.sortType,
            t;

        if (this.type) {
            if (Ext.isString(this.type)) {
                this.type = Ext.data.Types[this.type.toUpperCase()] || types.AUTO;
            }
        } else {
            this.type = types.AUTO;
        }


        if (Ext.isString(st)) {
            this.sortType = Ext.data.SortTypes[st];
        } else if (Ext.isEmpty(st)) {
            this.sortType = this.type.sortType;
        }

        if (!this.convert) {
            this.convert = this.type.convert;
        }
    },





    dateFormat: null,


    useNull: false,


    defaultValue: "",

    mapping: null,

    sortType: null,

    sortDir: "ASC",

    allowBlank: true
});

Ext.data.DataReader = function (meta, recordType) {

    this.meta = meta;

    this.recordType = Ext.isArray(recordType) ?
        Ext.data.Record.create(recordType) : recordType;


    if (this.recordType) {
        this.buildExtractors();
    }
};

Ext.data.DataReader.prototype = {


    getTotal: Ext.emptyFn,

    getRoot: Ext.emptyFn,

    getMessage: Ext.emptyFn,

    getSuccess: Ext.emptyFn,

    getId: Ext.emptyFn,

    buildExtractors: Ext.emptyFn,

    extractValues: Ext.emptyFn,


    realize: function (rs, data) {
        if (Ext.isArray(rs)) {
            for (var i = rs.length - 1; i >= 0; i--) {

                if (Ext.isArray(data)) {
                    this.realize(rs.splice(i, 1).shift(), data.splice(i, 1).shift());
                }
                else {


                    this.realize(rs.splice(i, 1).shift(), data);
                }
            }
        }
        else {

            if (Ext.isArray(data) && data.length == 1) {
                data = data.shift();
            }
            if (!this.isData(data)) {


                throw new Ext.data.DataReader.Error('realize', rs);
            }
            rs.phantom = false;
            rs._phid = rs.id;
            rs.id = this.getId(data);
            rs.data = data;

            rs.commit();
        }
    },


    update: function (rs, data) {
        if (Ext.isArray(rs)) {
            for (var i = rs.length - 1; i >= 0; i--) {
                if (Ext.isArray(data)) {
                    this.update(rs.splice(i, 1).shift(), data.splice(i, 1).shift());
                }
                else {


                    this.update(rs.splice(i, 1).shift(), data);
                }
            }
        }
        else {

            if (Ext.isArray(data) && data.length == 1) {
                data = data.shift();
            }
            if (this.isData(data)) {
                rs.data = Ext.apply(rs.data, data);
            }
            rs.commit();
        }
    },


    extractData: function (root, returnRecords) {

        var rawName = (this instanceof Ext.data.JsonReader) ? 'json' : 'node';

        var rs = [];



        if (this.isData(root) && !(this instanceof Ext.data.XmlReader)) {
            root = [root];
        }
        var f = this.recordType.prototype.fields,
            fi = f.items,
            fl = f.length,
            rs = [];
        if (returnRecords === true) {
            var Record = this.recordType;
            for (var i = 0; i < root.length; i++) {
                var n = root[i];
                var record = new Record(this.extractValues(n, fi, fl), this.getId(n));
                record[rawName] = n;
                rs.push(record);
            }
        }
        else {
            for (var i = 0; i < root.length; i++) {
                var data = this.extractValues(root[i], fi, fl);
                data[this.meta.idProperty] = this.getId(root[i]);
                rs.push(data);
            }
        }
        return rs;
    },


    isData: function (data) {
        return (data && Ext.isObject(data) && !Ext.isEmpty(this.getId(data))) ? true : false;
    },


    onMetaChange: function (meta) {
        delete this.ef;
        this.meta = meta;
        this.recordType = Ext.data.Record.create(meta.fields);
        this.buildExtractors();
    }
};


Ext.data.DataReader.Error = Ext.extend(Ext.Error, {
    constructor: function (message, arg) {
        this.arg = arg;
        Ext.Error.call(this, message);
    },
    name: 'Ext.data.DataReader'
});
Ext.apply(Ext.data.DataReader.Error.prototype, {
    lang: {
        'update': "#update received invalid data from server.  Please see docs for DataReader#update and review your DataReader configuration.",
        'realize': "#realize was called with invalid remote-data.  Please see the docs for DataReader#realize and review your DataReader configuration.",
        'invalid-response': "#readResponse received an invalid response from the server."
    }
});

Ext.data.DataWriter = function (config) {
    Ext.apply(this, config);
};
Ext.data.DataWriter.prototype = {


    writeAllFields: false,

    listful: false,


    apply: function (params, baseParams, action, rs) {
        var data = [],
        renderer = action + 'Record';

        if (Ext.isArray(rs)) {
            Ext.each(rs, function (rec) {
                data.push(this[renderer](rec));
            }, this);
        }
        else if (rs instanceof Ext.data.Record) {
            data = this[renderer](rs);
        }
        this.render(params, baseParams, data);
    },


    render: Ext.emptyFn,


    updateRecord: Ext.emptyFn,


    createRecord: Ext.emptyFn,


    destroyRecord: Ext.emptyFn,


    toHash: function (rec, config) {
        var map = rec.fields.map,
            data = {},
            raw = (this.writeAllFields === false && rec.phantom === false) ? rec.getChanges() : rec.data,
            m;
        Ext.iterate(raw, function (prop, value) {
            if ((m = map[prop])) {
                data[m.mapping ? m.mapping : m.name] = value;
            }
        });



        if (rec.phantom) {
            if (rec.fields.containsKey(this.meta.idProperty) && Ext.isEmpty(rec.data[this.meta.idProperty])) {
                delete data[this.meta.idProperty];
            }
        } else {
            data[this.meta.idProperty] = rec.id;
        }
        return data;
    },


    toArray: function (data) {
        var fields = [];
        Ext.iterate(data, function (k, v) { fields.push({ name: k, value: v }); }, this);
        return fields;
    }
};
Ext.data.DataProxy = function (conn) {


    conn = conn || {};





    this.api = conn.api;
    this.url = conn.url;
    this.restful = conn.restful;
    this.listeners = conn.listeners;


    this.prettyUrls = conn.prettyUrls;



    this.addEvents(

        'exception',

        'beforeload',

        'load',

        'loadexception',

        'beforewrite',

        'write'
    );
    Ext.data.DataProxy.superclass.constructor.call(this);


    try {
        Ext.data.Api.prepare(this);
    } catch (e) {
        if (e instanceof Ext.data.Api.Error) {
            e.toConsole();
        }
    }

    Ext.data.DataProxy.relayEvents(this, ['beforewrite', 'write', 'exception']);
};

Ext.extend(Ext.data.DataProxy, Ext.util.Observable, {

    restful: false,


    setApi: function () {
        if (arguments.length == 1) {
            var valid = Ext.data.Api.isValid(arguments[0]);
            if (valid === true) {
                this.api = arguments[0];
            }
            else {
                throw new Ext.data.Api.Error('invalid', valid);
            }
        }
        else if (arguments.length == 2) {
            if (!Ext.data.Api.isAction(arguments[0])) {
                throw new Ext.data.Api.Error('invalid', arguments[0]);
            }
            this.api[arguments[0]] = arguments[1];
        }
        Ext.data.Api.prepare(this);
    },


    isApiAction: function (action) {
        return (this.api[action]) ? true : false;
    },


    request: function (action, rs, params, reader, callback, scope, options) {
        if (!this.api[action] && !this.load) {
            throw new Ext.data.DataProxy.Error('action-undefined', action);
        }
        params = params || {};
        if ((action === Ext.data.Api.actions.read) ? this.fireEvent("beforeload", this, params) : this.fireEvent("beforewrite", this, action, rs, params) !== false) {
            this.doRequest.apply(this, arguments);
        }
        else {
            callback.call(scope || this, null, options, false);
        }
    },



    load: null,


    doRequest: function (action, rs, params, reader, callback, scope, options) {



        this.load(params, reader, callback, scope, options);
    },


    onRead: Ext.emptyFn,

    onWrite: Ext.emptyFn,

    buildUrl: function (action, record) {
        record = record || null;




        var url = (this.conn && this.conn.url) ? this.conn.url : (this.api[action]) ? this.api[action].url : this.url;
        if (!url) {
            throw new Ext.data.Api.Error('invalid-url', action);
        }







        var provides = null;
        var m = url.match(/(.*)(\.json|\.xml|\.html)$/);
        if (m) {
            provides = m[2];
            url = m[1];
        }

        if ((this.restful === true || this.prettyUrls === true) && record instanceof Ext.data.Record && !record.phantom) {
            url += '/' + record.id;
        }
        return (provides === null) ? url : url + provides;
    },


    destroy: function () {
        this.purgeListeners();
    }
});



Ext.apply(Ext.data.DataProxy, Ext.util.Observable.prototype);
Ext.util.Observable.call(Ext.data.DataProxy);


Ext.data.DataProxy.Error = Ext.extend(Ext.Error, {
    constructor: function (message, arg) {
        this.arg = arg;
        Ext.Error.call(this, message);
    },
    name: 'Ext.data.DataProxy'
});
Ext.apply(Ext.data.DataProxy.Error.prototype, {
    lang: {
        'action-undefined': "DataProxy attempted to execute an API-action but found an undefined url / function.  Please review your Proxy url/api-configuration.",
        'api-invalid': 'Recieved an invalid API-configuration.  Please ensure your proxy API-configuration contains only the actions from Ext.data.Api.actions.'
    }
});



Ext.data.Request = function (params) {
    Ext.apply(this, params);
};
Ext.data.Request.prototype = {

    action: undefined,

    rs: undefined,

    params: undefined,

    callback: Ext.emptyFn,

    scope: undefined,

    reader: undefined
};

Ext.data.Response = function (params) {
    Ext.apply(this, params);
};
Ext.data.Response.prototype = {

    action: undefined,

    success: undefined,

    message: undefined,

    data: undefined,

    raw: undefined,

    records: undefined
};

Ext.data.ScriptTagProxy = function (config) {
    Ext.apply(this, config);

    Ext.data.ScriptTagProxy.superclass.constructor.call(this, config);

    this.head = document.getElementsByTagName("head")[0];


};

Ext.data.ScriptTagProxy.TRANS_ID = 1000;

Ext.extend(Ext.data.ScriptTagProxy, Ext.data.DataProxy, {


    timeout: 30000,

    callbackParam: "callback",

    nocache: true,


    doRequest: function (action, rs, params, reader, callback, scope, arg) {
        var p = Ext.urlEncode(Ext.apply(params, this.extraParams));

        var url = this.buildUrl(action, rs);
        if (!url) {
            throw new Ext.data.Api.Error('invalid-url', url);
        }
        url = Ext.urlAppend(url, p);

        if (this.nocache) {
            url = Ext.urlAppend(url, '_dc=' + (new Date().getTime()));
        }
        var transId = ++Ext.data.ScriptTagProxy.TRANS_ID;
        var trans = {
            id: transId,
            action: action,
            cb: "stcCallback" + transId,
            scriptId: "stcScript" + transId,
            params: params,
            arg: arg,
            url: url,
            callback: callback,
            scope: scope,
            reader: reader
        };
        window[trans.cb] = this.createCallback(action, rs, trans);
        url += String.format("&{0}={1}", this.callbackParam, trans.cb);
        if (this.autoAbort !== false) {
            this.abort();
        }

        trans.timeoutId = this.handleFailure.defer(this.timeout, this, [trans]);

        var script = document.createElement("script");
        script.setAttribute("src", url);
        script.setAttribute("type", "text/javascript");
        script.setAttribute("id", trans.scriptId);
        this.head.appendChild(script);

        this.trans = trans;
    },


    createCallback: function (action, rs, trans) {
        var self = this;
        return function (res) {
            self.trans = false;
            self.destroyTrans(trans, true);
            if (action === Ext.data.Api.actions.read) {
                self.onRead.call(self, action, trans, res);
            } else {
                self.onWrite.call(self, action, trans, res, rs);
            }
        };
    },

    onRead: function (action, trans, res) {
        var result;
        try {
            result = trans.reader.readRecords(res);
        } catch (e) {

            this.fireEvent("loadexception", this, trans, res, e);

            this.fireEvent('exception', this, 'response', action, trans, res, e);
            trans.callback.call(trans.scope || window, null, trans.arg, false);
            return;
        }
        if (result.success === false) {

            this.fireEvent('loadexception', this, trans, res);

            this.fireEvent('exception', this, 'remote', action, trans, res, null);
        } else {
            this.fireEvent("load", this, res, trans.arg);
        }
        trans.callback.call(trans.scope || window, result, trans.arg, result.success);
    },

    onWrite: function (action, trans, response, rs) {
        var reader = trans.reader;
        try {

            var res = reader.readResponse(action, response);
        } catch (e) {
            this.fireEvent('exception', this, 'response', action, trans, res, e);
            trans.callback.call(trans.scope || window, null, res, false);
            return;
        }
        if (!res.success === true) {
            this.fireEvent('exception', this, 'remote', action, trans, res, rs);
            trans.callback.call(trans.scope || window, null, res, false);
            return;
        }
        this.fireEvent("write", this, action, res.data, res, rs, trans.arg);
        trans.callback.call(trans.scope || window, res.data, res, true);
    },


    isLoading: function () {
        return this.trans ? true : false;
    },


    abort: function () {
        if (this.isLoading()) {
            this.destroyTrans(this.trans);
        }
    },


    destroyTrans: function (trans, isLoaded) {
        this.head.removeChild(document.getElementById(trans.scriptId));
        clearTimeout(trans.timeoutId);
        if (isLoaded) {
            window[trans.cb] = undefined;
            try {
                delete window[trans.cb];
            } catch (e) { }
        } else {

            window[trans.cb] = function () {
                window[trans.cb] = undefined;
                try {
                    delete window[trans.cb];
                } catch (e) { }
            };
        }
    },


    handleFailure: function (trans) {
        this.trans = false;
        this.destroyTrans(trans, false);
        if (trans.action === Ext.data.Api.actions.read) {

            this.fireEvent("loadexception", this, null, trans.arg);
        }

        this.fireEvent('exception', this, 'response', trans.action, {
            response: null,
            options: trans.arg
        });
        trans.callback.call(trans.scope || window, null, trans.arg, false);
    },


    destroy: function () {
        this.abort();
        Ext.data.ScriptTagProxy.superclass.destroy.call(this);
    }
});
Ext.data.HttpProxy = function (conn) {
    Ext.data.HttpProxy.superclass.constructor.call(this, conn);


    this.conn = conn;





    this.conn.url = null;

    this.useAjax = !conn || !conn.events;


    var actions = Ext.data.Api.actions;
    this.activeRequest = {};
    for (var verb in actions) {
        this.activeRequest[actions[verb]] = undefined;
    }
};

Ext.extend(Ext.data.HttpProxy, Ext.data.DataProxy, {

    getConnection: function () {
        return this.useAjax ? Ext.Ajax : this.conn;
    },


    setUrl: function (url, makePermanent) {
        this.conn.url = url;
        if (makePermanent === true) {
            this.url = url;
            this.api = null;
            Ext.data.Api.prepare(this);
        }
    },


    doRequest: function (action, rs, params, reader, cb, scope, arg) {
        var o = {
            method: (this.api[action]) ? this.api[action]['method'] : undefined,
            request: {
                callback: cb,
                scope: scope,
                arg: arg
            },
            reader: reader,
            callback: this.createCallback(action, rs),
            scope: this
        };



        if (params.jsonData) {
            o.jsonData = params.jsonData;
        } else if (params.xmlData) {
            o.xmlData = params.xmlData;
        } else {
            o.params = params || {};
        }



        this.conn.url = this.buildUrl(action, rs);

        if (this.useAjax) {

            Ext.applyIf(o, this.conn);


            if (this.activeRequest[action]) {





            }
            this.activeRequest[action] = Ext.Ajax.request(o);
        } else {
            this.conn.request(o);
        }

        this.conn.url = null;
    },


    createCallback: function (action, rs) {
        return function (o, success, response) {
            this.activeRequest[action] = undefined;
            if (!success) {
                if (action === Ext.data.Api.actions.read) {


                    this.fireEvent('loadexception', this, o, response);
                }
                this.fireEvent('exception', this, 'response', action, o, response);
                o.request.callback.call(o.request.scope, null, o.request.arg, false);
                return;
            }
            if (action === Ext.data.Api.actions.read) {
                this.onRead(action, o, response);
            } else {
                this.onWrite(action, o, response, rs);
            }
        };
    },


    onRead: function (action, o, response) {
        var result;
        try {
            result = o.reader.read(response);
        } catch (e) {


            this.fireEvent('loadexception', this, o, response, e);

            this.fireEvent('exception', this, 'response', action, o, response, e);
            o.request.callback.call(o.request.scope, null, o.request.arg, false);
            return;
        }
        if (result.success === false) {


            this.fireEvent('loadexception', this, o, response);


            var res = o.reader.readResponse(action, response);
            this.fireEvent('exception', this, 'remote', action, o, res, null);
        }
        else {
            this.fireEvent('load', this, o, o.request.arg);
        }



        o.request.callback.call(o.request.scope, result, o.request.arg, result.success);
    },

    onWrite: function (action, o, response, rs) {
        var reader = o.reader;
        var res;
        try {
            res = reader.readResponse(action, response);
        } catch (e) {
            this.fireEvent('exception', this, 'response', action, o, response, e);
            o.request.callback.call(o.request.scope, null, o.request.arg, false);
            return;
        }
        if (res.success === true) {
            this.fireEvent('write', this, action, res.data, res, rs, o.request.arg);
        } else {
            this.fireEvent('exception', this, 'remote', action, o, res, rs);
        }



        o.request.callback.call(o.request.scope, res.data, res, res.success);
    },


    destroy: function () {
        if (!this.useAjax) {
            this.conn.abort();
        } else if (this.activeRequest) {
            var actions = Ext.data.Api.actions;
            for (var verb in actions) {
                if (this.activeRequest[actions[verb]]) {
                    Ext.Ajax.abort(this.activeRequest[actions[verb]]);
                }
            }
        }
        Ext.data.HttpProxy.superclass.destroy.call(this);
    }
});
Ext.data.MemoryProxy = function (data) {

    var api = {};
    api[Ext.data.Api.actions.read] = true;
    Ext.data.MemoryProxy.superclass.constructor.call(this, {
        api: api
    });
    this.data = data;
};

Ext.extend(Ext.data.MemoryProxy, Ext.data.DataProxy, {



    doRequest: function (action, rs, params, reader, callback, scope, arg) {

        params = params || {};
        var result;
        try {
            result = reader.readRecords(this.data);
        } catch (e) {

            this.fireEvent("loadexception", this, null, arg, e);

            this.fireEvent('exception', this, 'response', action, arg, null, e);
            callback.call(scope, null, arg, false);
            return;
        }
        callback.call(scope, result, arg, true);
    }
});
Ext.data.Types = new function () {
    var st = Ext.data.SortTypes;
    Ext.apply(this, {

        stripRe: /[\$,%]/g,


        AUTO: {
            convert: function (v) { return v; },
            sortType: st.none,
            type: 'auto'
        },


        STRING: {
            convert: function (v) { return (v === undefined || v === null) ? '' : String(v); },
            sortType: st.asUCString,
            type: 'string'
        },


        INT: {
            convert: function (v) {
                return v !== undefined && v !== null && v !== '' ?
                    parseInt(String(v).replace(Ext.data.Types.stripRe, ''), 10) : (this.useNull ? null : 0);
            },
            sortType: st.none,
            type: 'int'
        },


        FLOAT: {
            convert: function (v) {
                return v !== undefined && v !== null && v !== '' ?
                    parseFloat(String(v).replace(Ext.data.Types.stripRe, ''), 10) : (this.useNull ? null : 0);
            },
            sortType: st.none,
            type: 'float'
        },


        BOOL: {
            convert: function (v) { return v === true || v === 'true' || v == 1; },
            sortType: st.none,
            type: 'bool'
        },


        DATE: {
            convert: function (v) {
                var df = this.dateFormat;
                if (!v) {
                    return null;
                }
                if (Ext.isDate(v)) {
                    return v;
                }
                if (df) {
                    if (df == 'timestamp') {
                        return new Date(v * 1000);
                    }
                    if (df == 'time') {
                        return new Date(parseInt(v, 10));
                    }
                    return Date.parseDate(v, df);
                }
                var parsed = Date.parse(v);
                return parsed ? new Date(parsed) : null;
            },
            sortType: st.asDate,
            type: 'date'
        }
    });

    Ext.apply(this, {

        BOOLEAN: this.BOOL,

        INTEGER: this.INT,

        NUMBER: this.FLOAT
    });
};
Ext.data.JsonWriter = Ext.extend(Ext.data.DataWriter, {

    encode: true,

    encodeDelete: false,

    constructor: function (config) {
        Ext.data.JsonWriter.superclass.constructor.call(this, config);
    },


    render: function (params, baseParams, data) {
        if (this.encode === true) {

            Ext.apply(params, baseParams);
            params[this.meta.root] = Ext.encode(data);
        } else {

            var jdata = Ext.apply({}, baseParams);
            jdata[this.meta.root] = data;
            params.jsonData = jdata;
        }
    },

    createRecord: function (rec) {
        return this.toHash(rec);
    },

    updateRecord: function (rec) {
        return this.toHash(rec);

    },

    destroyRecord: function (rec) {
        if (this.encodeDelete) {
            var data = {};
            data[this.meta.idProperty] = rec.id;
            return data;
        } else {
            return rec.id;
        }
    }
});
Ext.data.JsonReader = function (meta, recordType) {
    meta = meta || {};




    Ext.applyIf(meta, {
        idProperty: 'id',
        successProperty: 'success',
        totalProperty: 'total'
    });

    Ext.data.JsonReader.superclass.constructor.call(this, meta, recordType || meta.fields);
};
Ext.extend(Ext.data.JsonReader, Ext.data.DataReader, {


    read: function (response) {
        var json = response.responseText;
        var o = Ext.decode(json);
        if (!o) {
            throw { message: 'JsonReader.read: Json object not found' };
        }
        return this.readRecords(o);
    },



    readResponse: function (action, response) {
        var o = (response.responseText !== undefined) ? Ext.decode(response.responseText) : response;
        if (!o) {
            throw new Ext.data.JsonReader.Error('response');
        }

        var root = this.getRoot(o);
        if (action === Ext.data.Api.actions.create) {
            var def = Ext.isDefined(root);
            if (def && Ext.isEmpty(root)) {
                throw new Ext.data.JsonReader.Error('root-empty', this.meta.root);
            }
            else if (!def) {
                throw new Ext.data.JsonReader.Error('root-undefined-response', this.meta.root);
            }
        }


        var res = new Ext.data.Response({
            action: action,
            success: this.getSuccess(o),
            data: (root) ? this.extractData(root, false) : [],
            message: this.getMessage(o),
            raw: o
        });


        if (Ext.isEmpty(res.success)) {
            throw new Ext.data.JsonReader.Error('successProperty-response', this.meta.successProperty);
        }
        return res;
    },


    readRecords: function (o) {

        this.jsonData = o;
        if (o.metaData) {
            this.onMetaChange(o.metaData);
        }
        var s = this.meta, Record = this.recordType,
            f = Record.prototype.fields, fi = f.items, fl = f.length, v;

        var root = this.getRoot(o), c = root.length, totalRecords = c, success = true;
        if (s.totalProperty) {
            v = parseInt(this.getTotal(o), 10);
            if (!isNaN(v)) {
                totalRecords = v;
            }
        }
        if (s.successProperty) {
            v = this.getSuccess(o);
            if (v === false || v === 'false') {
                success = false;
            }
        }


        return {
            success: success,
            records: this.extractData(root, true),
            totalRecords: totalRecords
        };
    },


    buildExtractors: function () {
        if (this.ef) {
            return;
        }
        var s = this.meta, Record = this.recordType,
            f = Record.prototype.fields, fi = f.items, fl = f.length;

        if (s.totalProperty) {
            this.getTotal = this.createAccessor(s.totalProperty);
        }
        if (s.successProperty) {
            this.getSuccess = this.createAccessor(s.successProperty);
        }
        if (s.messageProperty) {
            this.getMessage = this.createAccessor(s.messageProperty);
        }
        this.getRoot = s.root ? this.createAccessor(s.root) : function (p) { return p; };
        if (s.id || s.idProperty) {
            var g = this.createAccessor(s.id || s.idProperty);
            this.getId = function (rec) {
                var r = g(rec);
                return (r === undefined || r === '') ? null : r;
            };
        } else {
            this.getId = function () { return null; };
        }
        var ef = [];
        for (var i = 0; i < fl; i++) {
            f = fi[i];
            var map = (f.mapping !== undefined && f.mapping !== null) ? f.mapping : f.name;
            ef.push(this.createAccessor(map));
        }
        this.ef = ef;
    },


    simpleAccess: function (obj, subsc) {
        return obj[subsc];
    },


    createAccessor: function () {
        var re = /[\[\.]/;
        return function (expr) {
            if (Ext.isEmpty(expr)) {
                return Ext.emptyFn;
            }
            if (Ext.isFunction(expr)) {
                return expr;
            }
            var i = String(expr).search(re);
            if (i >= 0) {
                return new Function('obj', 'return obj' + (i > 0 ? '.' : '') + expr);
            }
            return function (obj) {
                return obj[expr];
            };

        };
    } (),


    extractValues: function (data, items, len) {
        var f, values = {};
        for (var j = 0; j < len; j++) {
            f = items[j];
            var v = this.ef[j](data);
            values[f.name] = f.convert((v !== undefined) ? v : f.defaultValue, data);
        }
        return values;
    }
});


Ext.data.JsonReader.Error = Ext.extend(Ext.Error, {
    constructor: function (message, arg) {
        this.arg = arg;
        Ext.Error.call(this, message);
    },
    name: 'Ext.data.JsonReader'
});
Ext.apply(Ext.data.JsonReader.Error.prototype, {
    lang: {
        'response': 'An error occurred while json-decoding your server response',
        'successProperty-response': 'Could not locate your "successProperty" in your server response.  Please review your JsonReader config to ensure the config-property "successProperty" matches the property in your server-response.  See the JsonReader docs.',
        'root-undefined-config': 'Your JsonReader was configured without a "root" property.  Please review your JsonReader config and make sure to define the root property.  See the JsonReader docs.',
        'idProperty-undefined': 'Your JsonReader was configured without an "idProperty"  Please review your JsonReader configuration and ensure the "idProperty" is set (e.g.: "id").  See the JsonReader docs.',
        'root-empty': 'Data was expected to be returned by the server in the "root" property of the response.  Please review your JsonReader configuration to ensure the "root" property matches that returned in the server-response.  See JsonReader docs.'
    }
});

Ext.data.ArrayReader = Ext.extend(Ext.data.JsonReader, {




    readRecords: function (o) {
        this.arrayData = o;
        var s = this.meta,
            sid = s ? Ext.num(s.idIndex, s.id) : null,
            recordType = this.recordType,
            fields = recordType.prototype.fields,
            records = [],
            success = true,
            v;

        var root = this.getRoot(o);

        for (var i = 0, len = root.length; i < len; i++) {
            var n = root[i],
                values = {},
                id = ((sid || sid === 0) && n[sid] !== undefined && n[sid] !== "" ? n[sid] : null);
            for (var j = 0, jlen = fields.length; j < jlen; j++) {
                var f = fields.items[j],
                    k = f.mapping !== undefined && f.mapping !== null ? f.mapping : j;
                v = n[k] !== undefined ? n[k] : f.defaultValue;
                v = f.convert(v, n);
                values[f.name] = v;
            }
            var record = new recordType(values, id);
            record.json = n;
            records[records.length] = record;
        }

        var totalRecords = records.length;

        if (s.totalProperty) {
            v = parseInt(this.getTotal(o), 10);
            if (!isNaN(v)) {
                totalRecords = v;
            }
        }
        if (s.successProperty) {
            v = this.getSuccess(o);
            if (v === false || v === 'false') {
                success = false;
            }
        }

        return {
            success: success,
            records: records,
            totalRecords: totalRecords
        };
    }
});
Ext.data.ArrayStore = Ext.extend(Ext.data.Store, {

    constructor: function (config) {
        Ext.data.ArrayStore.superclass.constructor.call(this, Ext.apply(config, {
            reader: new Ext.data.ArrayReader(config)
        }));
    },

    loadData: function (data, append) {
        if (this.expandData === true) {
            var r = [];
            for (var i = 0, len = data.length; i < len; i++) {
                r[r.length] = [data[i]];
            }
            data = r;
        }
        Ext.data.ArrayStore.superclass.loadData.call(this, data, append);
    }
});
Ext.reg('arraystore', Ext.data.ArrayStore);


Ext.data.SimpleStore = Ext.data.ArrayStore;
Ext.reg('simplestore', Ext.data.SimpleStore);
Ext.data.JsonStore = Ext.extend(Ext.data.Store, {

    constructor: function (config) {
        Ext.data.JsonStore.superclass.constructor.call(this, Ext.apply(config, {
            reader: new Ext.data.JsonReader(config)
        }));
    }
});
Ext.reg('jsonstore', Ext.data.JsonStore);
Ext.data.XmlWriter = function (params) {
    Ext.data.XmlWriter.superclass.constructor.apply(this, arguments);

    this.tpl = (typeof (this.tpl) === 'string') ? new Ext.XTemplate(this.tpl).compile() : this.tpl.compile();
};
Ext.extend(Ext.data.XmlWriter, Ext.data.DataWriter, {

    documentRoot: 'xrequest',

    forceDocumentRoot: false,

    root: 'records',

    xmlVersion: '1.0',

    xmlEncoding: 'ISO-8859-15',


    tpl: '<tpl for="."><\u003fxml version="{version}" encoding="{encoding}"\u003f><tpl if="documentRoot"><{documentRoot}><tpl for="baseParams"><tpl for="."><{name}>{value}</{name}></tpl></tpl></tpl><tpl if="records.length&gt;1"><{root}></tpl><tpl for="records"><{parent.record}><tpl for="."><{name}>{value}</{name}></tpl></{parent.record}></tpl><tpl if="records.length&gt;1"></{root}></tpl><tpl if="documentRoot"></{documentRoot}></tpl></tpl>',



    render: function (params, baseParams, data) {
        baseParams = this.toArray(baseParams);
        params.xmlData = this.tpl.applyTemplate({
            version: this.xmlVersion,
            encoding: this.xmlEncoding,
            documentRoot: (baseParams.length > 0 || this.forceDocumentRoot === true) ? this.documentRoot : false,
            record: this.meta.record,
            root: this.root,
            baseParams: baseParams,
            records: (Ext.isArray(data[0])) ? data : [data]
        });
    },


    createRecord: function (rec) {
        return this.toArray(this.toHash(rec));
    },


    updateRecord: function (rec) {
        return this.toArray(this.toHash(rec));

    },

    destroyRecord: function (rec) {
        var data = {};
        data[this.meta.idProperty] = rec.id;
        return this.toArray(data);
    }
});

Ext.data.XmlReader = function (meta, recordType) {
    meta = meta || {};


    Ext.applyIf(meta, {
        idProperty: meta.idProperty || meta.idPath || meta.id,
        successProperty: meta.successProperty || meta.success
    });

    Ext.data.XmlReader.superclass.constructor.call(this, meta, recordType || meta.fields);
};
Ext.extend(Ext.data.XmlReader, Ext.data.DataReader, {

    read: function (response) {
        var doc = response.responseXML;
        if (!doc) {
            throw { message: "XmlReader.read: XML Document not available" };
        }
        return this.readRecords(doc);
    },


    readRecords: function (doc) {

        this.xmlData = doc;

        var root = doc.documentElement || doc,
            q = Ext.DomQuery,
            totalRecords = 0,
            success = true;

        if (this.meta.totalProperty) {
            totalRecords = this.getTotal(root, 0);
        }
        if (this.meta.successProperty) {
            success = this.getSuccess(root);
        }

        var records = this.extractData(q.select(this.meta.record, root), true);


        return {
            success: success,
            records: records,
            totalRecords: totalRecords || records.length
        };
    },


    readResponse: function (action, response) {
        var q = Ext.DomQuery,
            doc = response.responseXML,
            root = doc.documentElement || doc;


        var res = new Ext.data.Response({
            action: action,
            success: this.getSuccess(root),
            message: this.getMessage(root),
            data: this.extractData(q.select(this.meta.record, root) || q.select(this.meta.root, root), false),
            raw: doc
        });

        if (Ext.isEmpty(res.success)) {
            throw new Ext.data.DataReader.Error('successProperty-response', this.meta.successProperty);
        }


        if (action === Ext.data.Api.actions.create) {
            var def = Ext.isDefined(res.data);
            if (def && Ext.isEmpty(res.data)) {
                throw new Ext.data.JsonReader.Error('root-empty', this.meta.root);
            }
            else if (!def) {
                throw new Ext.data.JsonReader.Error('root-undefined-response', this.meta.root);
            }
        }
        return res;
    },

    getSuccess: function () {
        return true;
    },


    buildExtractors: function () {
        if (this.ef) {
            return;
        }
        var s = this.meta,
            Record = this.recordType,
            f = Record.prototype.fields,
            fi = f.items,
            fl = f.length;

        if (s.totalProperty) {
            this.getTotal = this.createAccessor(s.totalProperty);
        }
        if (s.successProperty) {
            this.getSuccess = this.createAccessor(s.successProperty);
        }
        if (s.messageProperty) {
            this.getMessage = this.createAccessor(s.messageProperty);
        }
        this.getRoot = function (res) {
            return (!Ext.isEmpty(res[this.meta.record])) ? res[this.meta.record] : res[this.meta.root];
        };
        if (s.idPath || s.idProperty) {
            var g = this.createAccessor(s.idPath || s.idProperty);
            this.getId = function (rec) {
                var id = g(rec) || rec.id;
                return (id === undefined || id === '') ? null : id;
            };
        } else {
            this.getId = function () { return null; };
        }
        var ef = [];
        for (var i = 0; i < fl; i++) {
            f = fi[i];
            var map = (f.mapping !== undefined && f.mapping !== null) ? f.mapping : f.name;
            ef.push(this.createAccessor(map));
        }
        this.ef = ef;
    },


    createAccessor: function () {
        var q = Ext.DomQuery;
        return function (key) {
            switch (key) {
                case this.meta.totalProperty:
                    return function (root, def) {
                        return q.selectNumber(key, root, def);
                    };
                    break;
                case this.meta.successProperty:
                    return function (root, def) {
                        var sv = q.selectValue(key, root, true);
                        var success = sv !== false && sv !== 'false';
                        return success;
                    };
                    break;
                default:
                    return function (root, def) {
                        return q.selectValue(key, root, def);
                    };
                    break;
            }
        };
    } (),


    extractValues: function (data, items, len) {
        var f, values = {};
        for (var j = 0; j < len; j++) {
            f = items[j];
            var v = this.ef[j](data);
            values[f.name] = f.convert((v !== undefined) ? v : f.defaultValue, data);
        }
        return values;
    }
});
Ext.data.XmlStore = Ext.extend(Ext.data.Store, {

    constructor: function (config) {
        Ext.data.XmlStore.superclass.constructor.call(this, Ext.apply(config, {
            reader: new Ext.data.XmlReader(config)
        }));
    }
});
Ext.reg('xmlstore', Ext.data.XmlStore);
Ext.data.GroupingStore = Ext.extend(Ext.data.Store, {


    constructor: function (config) {
        config = config || {};





        this.hasMultiSort = true;
        this.multiSortInfo = this.multiSortInfo || { sorters: [] };

        var sorters = this.multiSortInfo.sorters,
            groupField = config.groupField || this.groupField,
            sortInfo = config.sortInfo || this.sortInfo,
            groupDir = config.groupDir || this.groupDir;


        if (groupField) {
            sorters.push({
                field: groupField,
                direction: groupDir
            });
        }


        if (sortInfo) {
            sorters.push(sortInfo);
        }

        Ext.data.GroupingStore.superclass.constructor.call(this, config);

        this.addEvents(

          'groupchange'
        );

        this.applyGroupField();
    },



    remoteGroup: false,

    groupOnSort: false,

    groupDir: 'ASC',


    clearGrouping: function () {
        this.groupField = false;

        if (this.remoteGroup) {
            if (this.baseParams) {
                delete this.baseParams.groupBy;
                delete this.baseParams.groupDir;
            }
            var lo = this.lastOptions;
            if (lo && lo.params) {
                delete lo.params.groupBy;
                delete lo.params.groupDir;
            }

            this.reload();
        } else {
            this.sort();
            this.fireEvent('datachanged', this);
        }
    },


    groupBy: function (field, forceRegroup, direction) {
        direction = direction ? (String(direction).toUpperCase() == 'DESC' ? 'DESC' : 'ASC') : this.groupDir;

        if (this.groupField == field && this.groupDir == direction && !forceRegroup) {
            return;
        }



        var sorters = this.multiSortInfo.sorters;
        if (sorters.length > 0 && sorters[0].field == this.groupField) {
            sorters.shift();
        }

        this.groupField = field;
        this.groupDir = direction;
        this.applyGroupField();

        var fireGroupEvent = function () {
            this.fireEvent('groupchange', this, this.getGroupState());
        };

        if (this.groupOnSort) {
            this.sort(field, direction);
            fireGroupEvent.call(this);
            return;
        }

        if (this.remoteGroup) {
            this.on('load', fireGroupEvent, this, { single: true });
            this.reload();
        } else {
            this.sort(sorters);
            fireGroupEvent.call(this);
        }
    },



    sort: function (fieldName, dir) {
        if (this.remoteSort) {
            return Ext.data.GroupingStore.superclass.sort.call(this, fieldName, dir);
        }

        var sorters = [];


        if (Ext.isArray(arguments[0])) {
            sorters = arguments[0];
        } else if (fieldName == undefined) {


            sorters = this.sortInfo ? [this.sortInfo] : [];
        } else {


            var field = this.fields.get(fieldName);
            if (!field) return false;

            var name = field.name,
                sortInfo = this.sortInfo || null,
                sortToggle = this.sortToggle ? this.sortToggle[name] : null;

            if (!dir) {
                if (sortInfo && sortInfo.field == name) {
                    dir = (this.sortToggle[name] || 'ASC').toggle('ASC', 'DESC');
                } else {
                    dir = field.sortDir;
                }
            }

            this.sortToggle[name] = dir;
            this.sortInfo = { field: name, direction: dir };

            sorters = [this.sortInfo];
        }


        if (this.groupField) {
            sorters.unshift({ direction: this.groupDir, field: this.groupField });
        }

        return this.multiSort.call(this, sorters, dir);
    },


    applyGroupField: function () {
        if (this.remoteGroup) {
            if (!this.baseParams) {
                this.baseParams = {};
            }

            Ext.apply(this.baseParams, {
                groupBy: this.groupField,
                groupDir: this.groupDir
            });

            var lo = this.lastOptions;
            if (lo && lo.params) {
                lo.params.groupDir = this.groupDir;


                delete lo.params.groupBy;
            }
        }
    },


    applyGrouping: function (alwaysFireChange) {
        if (this.groupField !== false) {
            this.groupBy(this.groupField, true, this.groupDir);
            return true;
        } else {
            if (alwaysFireChange === true) {
                this.fireEvent('datachanged', this);
            }
            return false;
        }
    },


    getGroupState: function () {
        return this.groupOnSort && this.groupField !== false ?
               (this.sortInfo ? this.sortInfo.field : undefined) : this.groupField;
    }
});
Ext.reg('groupingstore', Ext.data.GroupingStore);

Ext.data.DirectProxy = function (config) {
    Ext.apply(this, config);
    if (typeof this.paramOrder == 'string') {
        this.paramOrder = this.paramOrder.split(/[\s,|]/);
    }
    Ext.data.DirectProxy.superclass.constructor.call(this, config);
};

Ext.extend(Ext.data.DirectProxy, Ext.data.DataProxy, {

    paramOrder: undefined,


    paramsAsHash: true,


    directFn: undefined,


    doRequest: function (action, rs, params, reader, callback, scope, options) {
        var args = [],
            directFn = this.api[action] || this.directFn;

        switch (action) {
            case Ext.data.Api.actions.create:
                args.push(params.jsonData);
                break;
            case Ext.data.Api.actions.read:

                if (directFn.directCfg.method.len > 0) {
                    if (this.paramOrder) {
                        for (var i = 0, len = this.paramOrder.length; i < len; i++) {
                            args.push(params[this.paramOrder[i]]);
                        }
                    } else if (this.paramsAsHash) {
                        args.push(params);
                    }
                }
                break;
            case Ext.data.Api.actions.update:
                args.push(params.jsonData);
                break;
            case Ext.data.Api.actions.destroy:
                args.push(params.jsonData);
                break;
        }

        var trans = {
            params: params || {},
            request: {
                callback: callback,
                scope: scope,
                arg: options
            },
            reader: reader
        };

        args.push(this.createCallback(action, rs, trans), this);
        directFn.apply(window, args);
    },


    createCallback: function (action, rs, trans) {
        var me = this;
        return function (result, res) {
            if (!res.status) {

                if (action === Ext.data.Api.actions.read) {
                    me.fireEvent("loadexception", me, trans, res, null);
                }
                me.fireEvent('exception', me, 'remote', action, trans, res, null);
                trans.request.callback.call(trans.request.scope, null, trans.request.arg, false);
                return;
            }
            if (action === Ext.data.Api.actions.read) {
                me.onRead(action, trans, result, res);
            } else {
                me.onWrite(action, trans, result, res, rs);
            }
        };
    },


    onRead: function (action, trans, result, res) {
        var records;
        try {
            records = trans.reader.readRecords(result);
        }
        catch (ex) {

            this.fireEvent("loadexception", this, trans, res, ex);

            this.fireEvent('exception', this, 'response', action, trans, res, ex);
            trans.request.callback.call(trans.request.scope, null, trans.request.arg, false);
            return;
        }
        this.fireEvent("load", this, res, trans.request.arg);
        trans.request.callback.call(trans.request.scope, records, trans.request.arg, true);
    },

    onWrite: function (action, trans, result, res, rs) {
        var data = trans.reader.extractData(trans.reader.getRoot(result), false);
        var success = trans.reader.getSuccess(result);
        success = (success !== false);
        if (success) {
            this.fireEvent("write", this, action, data, res, rs, trans.request.arg);
        } else {
            this.fireEvent('exception', this, 'remote', action, trans, result, rs);
        }
        trans.request.callback.call(trans.request.scope, data, res, success);
    }
});

Ext.data.DirectStore = Ext.extend(Ext.data.Store, {
    constructor: function (config) {

        var c = Ext.apply({}, {
            batchTransactions: false
        }, config);
        Ext.data.DirectStore.superclass.constructor.call(this, Ext.apply(c, {
            proxy: Ext.isDefined(c.proxy) ? c.proxy : new Ext.data.DirectProxy(Ext.copyTo({}, c, 'paramOrder,paramsAsHash,directFn,api')),
            reader: (!Ext.isDefined(c.reader) && c.fields) ? new Ext.data.JsonReader(Ext.copyTo({}, c, 'totalProperty,root,idProperty'), c.fields) : c.reader
        }));
    }
});
Ext.reg('directstore', Ext.data.DirectStore);

Ext.Direct = Ext.extend(Ext.util.Observable, {



    exceptions: {
        TRANSPORT: 'xhr',
        PARSE: 'parse',
        LOGIN: 'login',
        SERVER: 'exception'
    },


    constructor: function () {
        this.addEvents(

            'event',

            'exception'
        );
        this.transactions = {};
        this.providers = {};
    },


    addProvider: function (provider) {
        var a = arguments;
        if (a.length > 1) {
            for (var i = 0, len = a.length; i < len; i++) {
                this.addProvider(a[i]);
            }
            return;
        }


        if (!provider.events) {
            provider = new Ext.Direct.PROVIDERS[provider.type](provider);
        }
        provider.id = provider.id || Ext.id();
        this.providers[provider.id] = provider;

        provider.on('data', this.onProviderData, this);
        provider.on('exception', this.onProviderException, this);


        if (!provider.isConnected()) {
            provider.connect();
        }

        return provider;
    },


    getProvider: function (id) {
        return this.providers[id];
    },

    removeProvider: function (id) {
        var provider = id.id ? id : this.providers[id];
        provider.un('data', this.onProviderData, this);
        provider.un('exception', this.onProviderException, this);
        delete this.providers[provider.id];
        return provider;
    },

    addTransaction: function (t) {
        this.transactions[t.tid] = t;
        return t;
    },

    removeTransaction: function (t) {
        delete this.transactions[t.tid || t];
        return t;
    },

    getTransaction: function (tid) {
        return this.transactions[tid.tid || tid];
    },

    onProviderData: function (provider, e) {
        if (Ext.isArray(e)) {
            for (var i = 0, len = e.length; i < len; i++) {
                this.onProviderData(provider, e[i]);
            }
            return;
        }
        if (e.name && e.name != 'event' && e.name != 'exception') {
            this.fireEvent(e.name, e);
        } else if (e.type == 'exception') {
            this.fireEvent('exception', e);
        }
        this.fireEvent('event', e, provider);
    },

    createEvent: function (response, extraProps) {
        return new Ext.Direct.eventTypes[response.type](Ext.apply(response, extraProps));
    }
});

Ext.Direct = new Ext.Direct();

Ext.Direct.TID = 1;
Ext.Direct.PROVIDERS = {};
Ext.Direct.Transaction = function (config) {
    Ext.apply(this, config);
    this.tid = ++Ext.Direct.TID;
    this.retryCount = 0;
};
Ext.Direct.Transaction.prototype = {
    send: function () {
        this.provider.queueTransaction(this);
    },

    retry: function () {
        this.retryCount++;
        this.send();
    },

    getProvider: function () {
        return this.provider;
    }
}; Ext.Direct.Event = function (config) {
    Ext.apply(this, config);
};

Ext.Direct.Event.prototype = {
    status: true,
    getData: function () {
        return this.data;
    }
};

Ext.Direct.RemotingEvent = Ext.extend(Ext.Direct.Event, {
    type: 'rpc',
    getTransaction: function () {
        return this.transaction || Ext.Direct.getTransaction(this.tid);
    }
});

Ext.Direct.ExceptionEvent = Ext.extend(Ext.Direct.RemotingEvent, {
    status: false,
    type: 'exception'
});

Ext.Direct.eventTypes = {
    'rpc': Ext.Direct.RemotingEvent,
    'event': Ext.Direct.Event,
    'exception': Ext.Direct.ExceptionEvent
};

Ext.direct.Provider = Ext.extend(Ext.util.Observable, {



    priority: 1,




    constructor: function (config) {
        Ext.apply(this, config);
        this.addEvents(

            'connect',

            'disconnect',

            'data',

            'exception'
        );
        Ext.direct.Provider.superclass.constructor.call(this, config);
    },


    isConnected: function () {
        return false;
    },


    connect: Ext.emptyFn,


    disconnect: Ext.emptyFn
});

Ext.direct.JsonProvider = Ext.extend(Ext.direct.Provider, {
    parseResponse: function (xhr) {
        if (!Ext.isEmpty(xhr.responseText)) {
            if (typeof xhr.responseText == 'object') {
                return xhr.responseText;
            }
            return Ext.decode(xhr.responseText);
        }
        return null;
    },

    getEvents: function (xhr) {
        var data = null;
        try {
            data = this.parseResponse(xhr);
        } catch (e) {
            var event = new Ext.Direct.ExceptionEvent({
                data: e,
                xhr: xhr,
                code: Ext.Direct.exceptions.PARSE,
                message: 'Error parsing json response: \n\n ' + data
            });
            return [event];
        }
        var events = [];
        if (Ext.isArray(data)) {
            for (var i = 0, len = data.length; i < len; i++) {
                events.push(Ext.Direct.createEvent(data[i]));
            }
        } else {
            events.push(Ext.Direct.createEvent(data));
        }
        return events;
    }
});
Ext.direct.PollingProvider = Ext.extend(Ext.direct.JsonProvider, {


    priority: 3,


    interval: 3000,






    constructor: function (config) {
        Ext.direct.PollingProvider.superclass.constructor.call(this, config);
        this.addEvents(

            'beforepoll',

            'poll'
        );
    },


    isConnected: function () {
        return !!this.pollTask;
    },


    connect: function () {
        if (this.url && !this.pollTask) {
            this.pollTask = Ext.TaskMgr.start({
                run: function () {
                    if (this.fireEvent('beforepoll', this) !== false) {
                        if (typeof this.url == 'function') {
                            this.url(this.baseParams);
                        } else {
                            Ext.Ajax.request({
                                url: this.url,
                                callback: this.onData,
                                scope: this,
                                params: this.baseParams
                            });
                        }
                    }
                },
                interval: this.interval,
                scope: this
            });
            this.fireEvent('connect', this);
        } else if (!this.url) {
            throw 'Error initializing PollingProvider, no url configured.';
        }
    },


    disconnect: function () {
        if (this.pollTask) {
            Ext.TaskMgr.stop(this.pollTask);
            delete this.pollTask;
            this.fireEvent('disconnect', this);
        }
    },


    onData: function (opt, success, xhr) {
        if (success) {
            var events = this.getEvents(xhr);
            for (var i = 0, len = events.length; i < len; i++) {
                var e = events[i];
                this.fireEvent('data', this, e);
            }
        } else {
            var e = new Ext.Direct.ExceptionEvent({
                data: e,
                code: Ext.Direct.exceptions.TRANSPORT,
                message: 'Unable to connect to the server.',
                xhr: xhr
            });
            this.fireEvent('data', this, e);
        }
    }
});

Ext.Direct.PROVIDERS['polling'] = Ext.direct.PollingProvider;
Ext.direct.RemotingProvider = Ext.extend(Ext.direct.JsonProvider, {









    enableBuffer: 10,


    maxRetries: 1,


    timeout: undefined,

    constructor: function (config) {
        Ext.direct.RemotingProvider.superclass.constructor.call(this, config);
        this.addEvents(

            'beforecall',

            'call'
        );
        this.namespace = (Ext.isString(this.namespace)) ? Ext.ns(this.namespace) : this.namespace || window;
        this.transactions = {};
        this.callBuffer = [];
    },


    initAPI: function () {
        var o = this.actions;
        for (var c in o) {
            var cls = this.namespace[c] || (this.namespace[c] = {}),
                ms = o[c];
            for (var i = 0, len = ms.length; i < len; i++) {
                var m = ms[i];
                cls[m.name] = this.createMethod(c, m);
            }
        }
    },


    isConnected: function () {
        return !!this.connected;
    },

    connect: function () {
        if (this.url) {
            this.initAPI();
            this.connected = true;
            this.fireEvent('connect', this);
        } else if (!this.url) {
            throw 'Error initializing RemotingProvider, no url configured.';
        }
    },

    disconnect: function () {
        if (this.connected) {
            this.connected = false;
            this.fireEvent('disconnect', this);
        }
    },

    onData: function (opt, success, xhr) {
        if (success) {
            var events = this.getEvents(xhr);
            for (var i = 0, len = events.length; i < len; i++) {
                var e = events[i],
                    t = this.getTransaction(e);
                this.fireEvent('data', this, e);
                if (t) {
                    this.doCallback(t, e, true);
                    Ext.Direct.removeTransaction(t);
                }
            }
        } else {
            var ts = [].concat(opt.ts);
            for (var i = 0, len = ts.length; i < len; i++) {
                var t = this.getTransaction(ts[i]);
                if (t && t.retryCount < this.maxRetries) {
                    t.retry();
                } else {
                    var e = new Ext.Direct.ExceptionEvent({
                        data: e,
                        transaction: t,
                        code: Ext.Direct.exceptions.TRANSPORT,
                        message: 'Unable to connect to the server.',
                        xhr: xhr
                    });
                    this.fireEvent('data', this, e);
                    if (t) {
                        this.doCallback(t, e, false);
                        Ext.Direct.removeTransaction(t);
                    }
                }
            }
        }
    },

    getCallData: function (t) {
        return {
            action: t.action,
            method: t.method,
            data: t.data,
            type: 'rpc',
            tid: t.tid
        };
    },

    doSend: function (data) {
        var o = {
            url: this.url,
            callback: this.onData,
            scope: this,
            ts: data,
            timeout: this.timeout
        }, callData;

        if (Ext.isArray(data)) {
            callData = [];
            for (var i = 0, len = data.length; i < len; i++) {
                callData.push(this.getCallData(data[i]));
            }
        } else {
            callData = this.getCallData(data);
        }

        if (this.enableUrlEncode) {
            var params = {};
            params[Ext.isString(this.enableUrlEncode) ? this.enableUrlEncode : 'data'] = Ext.encode(callData);
            o.params = params;
        } else {
            o.jsonData = callData;
        }
        Ext.Ajax.request(o);
    },

    combineAndSend: function () {
        var len = this.callBuffer.length;
        if (len > 0) {
            this.doSend(len == 1 ? this.callBuffer[0] : this.callBuffer);
            this.callBuffer = [];
        }
    },

    queueTransaction: function (t) {
        if (t.form) {
            this.processForm(t);
            return;
        }
        this.callBuffer.push(t);
        if (this.enableBuffer) {
            if (!this.callTask) {
                this.callTask = new Ext.util.DelayedTask(this.combineAndSend, this);
            }
            this.callTask.delay(Ext.isNumber(this.enableBuffer) ? this.enableBuffer : 10);
        } else {
            this.combineAndSend();
        }
    },

    doCall: function (c, m, args) {
        var data = null, hs = args[m.len], scope = args[m.len + 1];

        if (m.len !== 0) {
            data = args.slice(0, m.len);
        }

        var t = new Ext.Direct.Transaction({
            provider: this,
            args: args,
            action: c,
            method: m.name,
            data: data,
            cb: scope && Ext.isFunction(hs) ? hs.createDelegate(scope) : hs
        });

        if (this.fireEvent('beforecall', this, t, m) !== false) {
            Ext.Direct.addTransaction(t);
            this.queueTransaction(t);
            this.fireEvent('call', this, t, m);
        }
    },

    doForm: function (c, m, form, callback, scope) {
        var t = new Ext.Direct.Transaction({
            provider: this,
            action: c,
            method: m.name,
            args: [form, callback, scope],
            cb: scope && Ext.isFunction(callback) ? callback.createDelegate(scope) : callback,
            isForm: true
        });

        if (this.fireEvent('beforecall', this, t, m) !== false) {
            Ext.Direct.addTransaction(t);
            var isUpload = String(form.getAttribute("enctype")).toLowerCase() == 'multipart/form-data',
                params = {
                    extTID: t.tid,
                    extAction: c,
                    extMethod: m.name,
                    extType: 'rpc',
                    extUpload: String(isUpload)
                };



            Ext.apply(t, {
                form: Ext.getDom(form),
                isUpload: isUpload,
                params: callback && Ext.isObject(callback.params) ? Ext.apply(params, callback.params) : params
            });
            this.fireEvent('call', this, t, m);
            this.processForm(t);
        }
    },

    processForm: function (t) {
        Ext.Ajax.request({
            url: this.url,
            params: t.params,
            callback: this.onData,
            scope: this,
            form: t.form,
            isUpload: t.isUpload,
            ts: t
        });
    },

    createMethod: function (c, m) {
        var f;
        if (!m.formHandler) {
            f = function () {
                this.doCall(c, m, Array.prototype.slice.call(arguments, 0));
            } .createDelegate(this);
        } else {
            f = function (form, callback, scope) {
                this.doForm(c, m, form, callback, scope);
            } .createDelegate(this);
        }
        f.directCfg = {
            action: c,
            method: m
        };
        return f;
    },

    getTransaction: function (opt) {
        return opt && opt.tid ? Ext.Direct.getTransaction(opt.tid) : null;
    },

    doCallback: function (t, e) {
        var fn = e.status ? 'success' : 'failure';
        if (t && t.cb) {
            var hs = t.cb,
                result = Ext.isDefined(e.result) ? e.result : e.data;
            if (Ext.isFunction(hs)) {
                hs(result, e);
            } else {
                Ext.callback(hs[fn], hs.scope, [result, e]);
                Ext.callback(hs.callback, hs.scope, [result, e]);
            }
        }
    }
});
Ext.Direct.PROVIDERS['remoting'] = Ext.direct.RemotingProvider;
Ext.Resizable = Ext.extend(Ext.util.Observable, {

    constructor: function (el, config) {
        this.el = Ext.get(el);
        if (config && config.wrap) {
            config.resizeChild = this.el;
            this.el = this.el.wrap(typeof config.wrap == 'object' ? config.wrap : { cls: 'xresizable-wrap' });
            this.el.id = this.el.dom.id = config.resizeChild.id + '-rzwrap';
            this.el.setStyle('overflow', 'hidden');
            this.el.setPositioning(config.resizeChild.getPositioning());
            config.resizeChild.clearPositioning();
            if (!config.width || !config.height) {
                var csize = config.resizeChild.getSize();
                this.el.setSize(csize.width, csize.height);
            }
            if (config.pinned && !config.adjustments) {
                config.adjustments = 'auto';
            }
        }


        this.proxy = this.el.createProxy({ tag: 'div', cls: 'x-resizable-proxy', id: this.el.id + '-rzproxy' }, Ext.getBody());
        this.proxy.unselectable();
        this.proxy.enableDisplayMode('block');

        Ext.apply(this, config);

        if (this.pinned) {
            this.disableTrackOver = true;
            this.el.addClass('x-resizable-pinned');
        }

        var position = this.el.getStyle('position');
        if (position != 'absolute' && position != 'fixed') {
            this.el.setStyle('position', 'relative');
        }
        if (!this.handles) {
            this.handles = 's,e,se';
            if (this.multiDirectional) {
                this.handles += ',n,w';
            }
        }
        if (this.handles == 'all') {
            this.handles = 'n s e w ne nw se sw';
        }
        var hs = this.handles.split(/\s*?[,;]\s*?| /);
        var ps = Ext.Resizable.positions;
        for (var i = 0, len = hs.length; i < len; i++) {
            if (hs[i] && ps[hs[i]]) {
                var pos = ps[hs[i]];
                this[pos] = new Ext.Resizable.Handle(this, pos, this.disableTrackOver, this.transparent, this.handleCls);
            }
        }

        this.corner = this.southeast;

        if (this.handles.indexOf('n') != -1 || this.handles.indexOf('w') != -1) {
            this.updateBox = true;
        }

        this.activeHandle = null;

        if (this.resizeChild) {
            if (typeof this.resizeChild == 'boolean') {
                this.resizeChild = Ext.get(this.el.dom.firstChild, true);
            } else {
                this.resizeChild = Ext.get(this.resizeChild, true);
            }
        }

        if (this.adjustments == 'auto') {
            var rc = this.resizeChild;
            var hw = this.west, he = this.east, hn = this.north, hs = this.south;
            if (rc && (hw || hn)) {
                rc.position('relative');
                rc.setLeft(hw ? hw.el.getWidth() : 0);
                rc.setTop(hn ? hn.el.getHeight() : 0);
            }
            this.adjustments = [
                (he ? -he.el.getWidth() : 0) + (hw ? -hw.el.getWidth() : 0),
                (hn ? -hn.el.getHeight() : 0) + (hs ? -hs.el.getHeight() : 0) - 1
            ];
        }

        if (this.draggable) {
            this.dd = this.dynamic ?
                this.el.initDD(null) : this.el.initDDProxy(null, { dragElId: this.proxy.id });
            this.dd.setHandleElId(this.resizeChild ? this.resizeChild.id : this.el.id);
            if (this.constrainTo) {
                this.dd.constrainTo(this.constrainTo);
            }
        }

        this.addEvents(

            'beforeresize',

            'resize'
        );

        if (this.width !== null && this.height !== null) {
            this.resizeTo(this.width, this.height);
        } else {
            this.updateChildSize();
        }
        if (Ext.isIE) {
            this.el.dom.style.zoom = 1;
        }
        Ext.Resizable.superclass.constructor.call(this);
    },


    adjustments: [0, 0],

    animate: false,


    disableTrackOver: false,

    draggable: false,

    duration: 0.35,

    dynamic: false,

    easing: 'easeOutStrong',

    enabled: true,


    handles: false,

    multiDirectional: false,

    height: null,

    width: null,

    heightIncrement: 0,

    widthIncrement: 0,

    minHeight: 5,

    minWidth: 5,

    maxHeight: 10000,

    maxWidth: 10000,

    minX: 0,

    minY: 0,

    pinned: false,

    preserveRatio: false,

    resizeChild: false,

    transparent: false,






    resizeTo: function (width, height) {
        this.el.setSize(width, height);
        this.updateChildSize();
        this.fireEvent('resize', this, width, height, null);
    },


    startSizing: function (e, handle) {
        this.fireEvent('beforeresize', this, e);
        if (this.enabled) {

            if (!this.overlay) {
                this.overlay = this.el.createProxy({ tag: 'div', cls: 'x-resizable-overlay', html: '&#160;' }, Ext.getBody());
                this.overlay.unselectable();
                this.overlay.enableDisplayMode('block');
                this.overlay.on({
                    scope: this,
                    mousemove: this.onMouseMove,
                    mouseup: this.onMouseUp
                });
            }
            this.overlay.setStyle('cursor', handle.el.getStyle('cursor'));

            this.resizing = true;
            this.startBox = this.el.getBox();
            this.startPoint = e.getXY();
            this.offsets = [(this.startBox.x + this.startBox.width) - this.startPoint[0],
                            (this.startBox.y + this.startBox.height) - this.startPoint[1]];

            this.overlay.setSize(Ext.lib.Dom.getViewWidth(true), Ext.lib.Dom.getViewHeight(true));
            this.overlay.show();

            if (this.constrainTo) {
                var ct = Ext.get(this.constrainTo);
                this.resizeRegion = ct.getRegion().adjust(
                    ct.getFrameWidth('t'),
                    ct.getFrameWidth('l'),
                    -ct.getFrameWidth('b'),
                    -ct.getFrameWidth('r')
                );
            }

            this.proxy.setStyle('visibility', 'hidden');
            this.proxy.show();
            this.proxy.setBox(this.startBox);
            if (!this.dynamic) {
                this.proxy.setStyle('visibility', 'visible');
            }
        }
    },


    onMouseDown: function (handle, e) {
        if (this.enabled) {
            e.stopEvent();
            this.activeHandle = handle;
            this.startSizing(e, handle);
        }
    },


    onMouseUp: function (e) {
        this.activeHandle = null;
        var size = this.resizeElement();
        this.resizing = false;
        this.handleOut();
        this.overlay.hide();
        this.proxy.hide();
        this.fireEvent('resize', this, size.width, size.height, e);
    },


    updateChildSize: function () {
        if (this.resizeChild) {
            var el = this.el;
            var child = this.resizeChild;
            var adj = this.adjustments;
            if (el.dom.offsetWidth) {
                var b = el.getSize(true);
                child.setSize(b.width + adj[0], b.height + adj[1]);
            }




            if (Ext.isIE) {
                setTimeout(function () {
                    if (el.dom.offsetWidth) {
                        var b = el.getSize(true);
                        child.setSize(b.width + adj[0], b.height + adj[1]);
                    }
                }, 10);
            }
        }
    },


    snap: function (value, inc, min) {
        if (!inc || !value) {
            return value;
        }
        var newValue = value;
        var m = value % inc;
        if (m > 0) {
            if (m > (inc / 2)) {
                newValue = value + (inc - m);
            } else {
                newValue = value - m;
            }
        }
        return Math.max(min, newValue);
    },


    resizeElement: function () {
        var box = this.proxy.getBox();
        if (this.updateBox) {
            this.el.setBox(box, false, this.animate, this.duration, null, this.easing);
        } else {
            this.el.setSize(box.width, box.height, this.animate, this.duration, null, this.easing);
        }
        this.updateChildSize();
        if (!this.dynamic) {
            this.proxy.hide();
        }
        if (this.draggable && this.constrainTo) {
            this.dd.resetConstraints();
            this.dd.constrainTo(this.constrainTo);
        }
        return box;
    },


    constrain: function (v, diff, m, mx) {
        if (v - diff < m) {
            diff = v - m;
        } else if (v - diff > mx) {
            diff = v - mx;
        }
        return diff;
    },


    onMouseMove: function (e) {
        if (this.enabled && this.activeHandle) {
            try {

                if (this.resizeRegion && !this.resizeRegion.contains(e.getPoint())) {
                    return;
                }


                var curSize = this.curSize || this.startBox,
                x = this.startBox.x, y = this.startBox.y,
                ox = x,
                oy = y,
                w = curSize.width,
                h = curSize.height,
                ow = w,
                oh = h,
                mw = this.minWidth,
                mh = this.minHeight,
                mxw = this.maxWidth,
                mxh = this.maxHeight,
                wi = this.widthIncrement,
                hi = this.heightIncrement,
                eventXY = e.getXY(),
                diffX = -(this.startPoint[0] - Math.max(this.minX, eventXY[0])),
                diffY = -(this.startPoint[1] - Math.max(this.minY, eventXY[1])),
                pos = this.activeHandle.position,
                tw,
                th;

                switch (pos) {
                    case 'east':
                        w += diffX;
                        w = Math.min(Math.max(mw, w), mxw);
                        break;
                    case 'south':
                        h += diffY;
                        h = Math.min(Math.max(mh, h), mxh);
                        break;
                    case 'southeast':
                        w += diffX;
                        h += diffY;
                        w = Math.min(Math.max(mw, w), mxw);
                        h = Math.min(Math.max(mh, h), mxh);
                        break;
                    case 'north':
                        diffY = this.constrain(h, diffY, mh, mxh);
                        y += diffY;
                        h -= diffY;
                        break;
                    case 'west':
                        diffX = this.constrain(w, diffX, mw, mxw);
                        x += diffX;
                        w -= diffX;
                        break;
                    case 'northeast':
                        w += diffX;
                        w = Math.min(Math.max(mw, w), mxw);
                        diffY = this.constrain(h, diffY, mh, mxh);
                        y += diffY;
                        h -= diffY;
                        break;
                    case 'northwest':
                        diffX = this.constrain(w, diffX, mw, mxw);
                        diffY = this.constrain(h, diffY, mh, mxh);
                        y += diffY;
                        h -= diffY;
                        x += diffX;
                        w -= diffX;
                        break;
                    case 'southwest':
                        diffX = this.constrain(w, diffX, mw, mxw);
                        h += diffY;
                        h = Math.min(Math.max(mh, h), mxh);
                        x += diffX;
                        w -= diffX;
                        break;
                }

                var sw = this.snap(w, wi, mw);
                var sh = this.snap(h, hi, mh);
                if (sw != w || sh != h) {
                    switch (pos) {
                        case 'northeast':
                            y -= sh - h;
                            break;
                        case 'north':
                            y -= sh - h;
                            break;
                        case 'southwest':
                            x -= sw - w;
                            break;
                        case 'west':
                            x -= sw - w;
                            break;
                        case 'northwest':
                            x -= sw - w;
                            y -= sh - h;
                            break;
                    }
                    w = sw;
                    h = sh;
                }

                if (this.preserveRatio) {
                    switch (pos) {
                        case 'southeast':
                        case 'east':
                            h = oh * (w / ow);
                            h = Math.min(Math.max(mh, h), mxh);
                            w = ow * (h / oh);
                            break;
                        case 'south':
                            w = ow * (h / oh);
                            w = Math.min(Math.max(mw, w), mxw);
                            h = oh * (w / ow);
                            break;
                        case 'northeast':
                            w = ow * (h / oh);
                            w = Math.min(Math.max(mw, w), mxw);
                            h = oh * (w / ow);
                            break;
                        case 'north':
                            tw = w;
                            w = ow * (h / oh);
                            w = Math.min(Math.max(mw, w), mxw);
                            h = oh * (w / ow);
                            x += (tw - w) / 2;
                            break;
                        case 'southwest':
                            h = oh * (w / ow);
                            h = Math.min(Math.max(mh, h), mxh);
                            tw = w;
                            w = ow * (h / oh);
                            x += tw - w;
                            break;
                        case 'west':
                            th = h;
                            h = oh * (w / ow);
                            h = Math.min(Math.max(mh, h), mxh);
                            y += (th - h) / 2;
                            tw = w;
                            w = ow * (h / oh);
                            x += tw - w;
                            break;
                        case 'northwest':
                            tw = w;
                            th = h;
                            h = oh * (w / ow);
                            h = Math.min(Math.max(mh, h), mxh);
                            w = ow * (h / oh);
                            y += th - h;
                            x += tw - w;
                            break;

                    }
                }
                this.proxy.setBounds(x, y, w, h);
                if (this.dynamic) {
                    this.resizeElement();
                }
            } catch (ex) { }
        }
    },


    handleOver: function () {
        if (this.enabled) {
            this.el.addClass('x-resizable-over');
        }
    },


    handleOut: function () {
        if (!this.resizing) {
            this.el.removeClass('x-resizable-over');
        }
    },


    getEl: function () {
        return this.el;
    },


    getResizeChild: function () {
        return this.resizeChild;
    },


    destroy: function (removeEl) {
        Ext.destroy(this.dd, this.overlay, this.proxy);
        this.overlay = null;
        this.proxy = null;

        var ps = Ext.Resizable.positions;
        for (var k in ps) {
            if (typeof ps[k] != 'function' && this[ps[k]]) {
                this[ps[k]].destroy();
            }
        }
        if (removeEl) {
            this.el.update('');
            Ext.destroy(this.el);
            this.el = null;
        }
        this.purgeListeners();
    },

    syncHandleHeight: function () {
        var h = this.el.getHeight(true);
        if (this.west) {
            this.west.el.setHeight(h);
        }
        if (this.east) {
            this.east.el.setHeight(h);
        }
    }
});



Ext.Resizable.positions = {
    n: 'north', s: 'south', e: 'east', w: 'west', se: 'southeast', sw: 'southwest', nw: 'northwest', ne: 'northeast'
};

Ext.Resizable.Handle = Ext.extend(Object, {
    constructor: function (rz, pos, disableTrackOver, transparent, cls) {
        if (!this.tpl) {

            var tpl = Ext.DomHelper.createTemplate(
                { tag: 'div', cls: 'x-resizable-handle x-resizable-handle-{0}' }
            );
            tpl.compile();
            Ext.Resizable.Handle.prototype.tpl = tpl;
        }
        this.position = pos;
        this.rz = rz;
        this.el = this.tpl.append(rz.el.dom, [this.position], true);
        this.el.unselectable();
        if (transparent) {
            this.el.setOpacity(0);
        }
        if (!Ext.isEmpty(cls)) {
            this.el.addClass(cls);
        }
        this.el.on('mousedown', this.onMouseDown, this);
        if (!disableTrackOver) {
            this.el.on({
                scope: this,
                mouseover: this.onMouseOver,
                mouseout: this.onMouseOut
            });
        }
    },


    afterResize: function (rz) {

    },

    onMouseDown: function (e) {
        this.rz.onMouseDown(this, e);
    },

    onMouseOver: function (e) {
        this.rz.handleOver(this, e);
    },

    onMouseOut: function (e) {
        this.rz.handleOut(this, e);
    },

    destroy: function () {
        Ext.destroy(this.el);
        this.el = null;
    }
});

Ext.Window = Ext.extend(Ext.Panel, {












    baseCls: 'x-window',

    resizable: true,

    draggable: true,

    closable: true,

    closeAction: 'close',

    constrain: false,

    constrainHeader: false,

    plain: false,

    minimizable: false,

    maximizable: false,

    minHeight: 100,

    minWidth: 200,

    expandOnShow: true,


    showAnimDuration: 0.25,


    hideAnimDuration: 0.25,


    collapsible: false,


    initHidden: undefined,


    hidden: true,






    elements: 'header,body',

    frame: true,

    floating: true,


    initComponent: function () {
        this.initTools();
        Ext.Window.superclass.initComponent.call(this);
        this.addEvents(



            'resize',

            'maximize',

            'minimize',

            'restore'
        );

        if (Ext.isDefined(this.initHidden)) {
            this.hidden = this.initHidden;
        }
        if (this.hidden === false) {
            this.hidden = true;
            this.show();
        }
    },


    getState: function () {
        return Ext.apply(Ext.Window.superclass.getState.call(this) || {}, this.getBox(true));
    },


    onRender: function (ct, position) {
        Ext.Window.superclass.onRender.call(this, ct, position);

        if (this.plain) {
            this.el.addClass('x-window-plain');
        }


        this.focusEl = this.el.createChild({
            tag: 'a', href: '#', cls: 'x-dlg-focus',
            tabIndex: '-1', html: '&#160;'
        });
        this.focusEl.swallowEvent('click', true);

        this.proxy = this.el.createProxy('x-window-proxy');
        this.proxy.enableDisplayMode('block');

        if (this.modal) {
            this.mask = this.container.createChild({ cls: 'ext-el-mask' }, this.el.dom);
            this.mask.enableDisplayMode('block');
            this.mask.hide();
            this.mon(this.mask, 'click', this.focus, this);
        }
        if (this.maximizable) {
            this.mon(this.header, 'dblclick', this.toggleMaximize, this);
        }
    },


    initEvents: function () {
        Ext.Window.superclass.initEvents.call(this);
        if (this.animateTarget) {
            this.setAnimateTarget(this.animateTarget);
        }

        if (this.resizable) {
            this.resizer = new Ext.Resizable(this.el, {
                minWidth: this.minWidth,
                minHeight: this.minHeight,
                handles: this.resizeHandles || 'all',
                pinned: true,
                resizeElement: this.resizerAction,
                handleCls: 'x-window-handle'
            });
            this.resizer.window = this;
            this.mon(this.resizer, 'beforeresize', this.beforeResize, this);
        }

        if (this.draggable) {
            this.header.addClass('x-window-draggable');
        }
        this.mon(this.el, 'mousedown', this.toFront, this);
        this.manager = this.manager || Ext.WindowMgr;
        this.manager.register(this);
        if (this.maximized) {
            this.maximized = false;
            this.maximize();
        }
        if (this.closable) {
            var km = this.getKeyMap();
            km.on(27, this.onEsc, this);
            km.disable();
        }
    },

    initDraggable: function () {

        this.dd = new Ext.Window.DD(this);
    },


    onEsc: function (k, e) {
        e.stopEvent();
        this[this.closeAction]();
    },


    beforeDestroy: function () {
        if (this.rendered) {
            this.hide();
            this.clearAnchor();
            Ext.destroy(
                this.focusEl,
                this.resizer,
                this.dd,
                this.proxy,
                this.mask
            );
        }
        Ext.Window.superclass.beforeDestroy.call(this);
    },


    onDestroy: function () {
        if (this.manager) {
            this.manager.unregister(this);
        }
        Ext.Window.superclass.onDestroy.call(this);
    },


    initTools: function () {
        if (this.minimizable) {
            this.addTool({
                id: 'minimize',
                handler: this.minimize.createDelegate(this, [])
            });
        }
        if (this.maximizable) {
            this.addTool({
                id: 'maximize',
                handler: this.maximize.createDelegate(this, [])
            });
            this.addTool({
                id: 'restore',
                handler: this.restore.createDelegate(this, []),
                hidden: true
            });
        }
        if (this.closable) {
            this.addTool({
                id: 'close',
                handler: this[this.closeAction].createDelegate(this, [])
            });
        }
    },


    resizerAction: function () {
        var box = this.proxy.getBox();
        this.proxy.hide();
        this.window.handleResize(box);
        return box;
    },


    beforeResize: function () {
        this.resizer.minHeight = Math.max(this.minHeight, this.getFrameHeight() + 40);
        this.resizer.minWidth = Math.max(this.minWidth, this.getFrameWidth() + 40);
        this.resizeBox = this.el.getBox();
    },


    updateHandles: function () {
        if (Ext.isIE && this.resizer) {
            this.resizer.syncHandleHeight();
            this.el.repaint();
        }
    },


    handleResize: function (box) {
        var rz = this.resizeBox;
        if (rz.x != box.x || rz.y != box.y) {
            this.updateBox(box);
        } else {
            this.setSize(box);
            if (Ext.isIE6 && Ext.isStrict) {
                this.doLayout();
            }
        }
        this.focus();
        this.updateHandles();
        this.saveState();
    },


    focus: function () {
        var f = this.focusEl,
            db = this.defaultButton,
            t = typeof db,
            el,
            ct;
        if (Ext.isDefined(db)) {
            if (Ext.isNumber(db) && this.fbar) {
                f = this.fbar.items.get(db);
            } else if (Ext.isString(db)) {
                f = Ext.getCmp(db);
            } else {
                f = db;
            }
            el = f.getEl();
            ct = Ext.getDom(this.container);
            if (el && ct) {
                if (ct != document.body && !Ext.lib.Region.getRegion(ct).contains(Ext.lib.Region.getRegion(el.dom))) {
                    return;
                }
            }
        }
        f = f || this.focusEl;
        f.focus.defer(10, f);
    },


    setAnimateTarget: function (el) {
        el = Ext.get(el);
        this.animateTarget = el;
    },


    beforeShow: function () {
        delete this.el.lastXY;
        delete this.el.lastLT;
        if (this.x === undefined || this.y === undefined) {
            var xy = this.el.getAlignToXY(this.container, 'c-c');
            var pos = this.el.translatePoints(xy[0], xy[1]);
            this.x = this.x === undefined ? pos.left : this.x;
            this.y = this.y === undefined ? pos.top : this.y;
        }
        this.el.setLeftTop(this.x, this.y);

        if (this.expandOnShow) {
            this.expand(false);
        }

        if (this.modal) {
            Ext.getBody().addClass('x-body-masked');
            this.mask.setSize(Ext.lib.Dom.getViewWidth(true), Ext.lib.Dom.getViewHeight(true));
            this.mask.show();
        }
    },


    show: function (animateTarget, cb, scope) {
        if (!this.rendered) {
            this.render(Ext.getBody());
        }
        if (this.hidden === false) {
            this.toFront();
            return this;
        }
        if (this.fireEvent('beforeshow', this) === false) {
            return this;
        }
        if (cb) {
            this.on('show', cb, scope, { single: true });
        }
        this.hidden = false;
        if (Ext.isDefined(animateTarget)) {
            this.setAnimateTarget(animateTarget);
        }
        this.beforeShow();
        if (this.animateTarget) {
            this.animShow();
        } else {
            this.afterShow();
        }
        return this;
    },


    afterShow: function (isAnim) {
        if (this.isDestroyed) {
            return false;
        }
        this.proxy.hide();
        this.el.setStyle('display', 'block');
        this.el.show();
        if (this.maximized) {
            this.fitContainer();
        }
        if (Ext.isMac && Ext.isGecko2) {
            this.cascade(this.setAutoScroll);
        }

        if (this.monitorResize || this.modal || this.constrain || this.constrainHeader) {
            Ext.EventManager.onWindowResize(this.onWindowResize, this);
        }
        this.doConstrain();
        this.doLayout();
        if (this.keyMap) {
            this.keyMap.enable();
        }
        this.toFront();
        this.updateHandles();
        if (isAnim && (Ext.isIE || Ext.isWebKit)) {
            var sz = this.getSize();
            this.onResize(sz.width, sz.height);
        }
        this.onShow();
        this.fireEvent('show', this);
    },


    animShow: function () {
        this.proxy.show();
        this.proxy.setBox(this.animateTarget.getBox());
        this.proxy.setOpacity(0);
        var b = this.getBox();
        this.el.setStyle('display', 'none');
        this.proxy.shift(Ext.apply(b, {
            callback: this.afterShow.createDelegate(this, [true], false),
            scope: this,
            easing: 'easeNone',
            duration: this.showAnimDuration,
            opacity: 0.5
        }));
    },


    hide: function (animateTarget, cb, scope) {
        if (this.hidden || this.fireEvent('beforehide', this) === false) {
            return this;
        }
        if (cb) {
            this.on('hide', cb, scope, { single: true });
        }
        this.hidden = true;
        if (animateTarget !== undefined) {
            this.setAnimateTarget(animateTarget);
        }
        if (this.modal) {
            this.mask.hide();
            Ext.getBody().removeClass('x-body-masked');
        }
        if (this.animateTarget) {
            this.animHide();
        } else {
            this.el.hide();
            this.afterHide();
        }
        return this;
    },


    afterHide: function () {
        this.proxy.hide();
        if (this.monitorResize || this.modal || this.constrain || this.constrainHeader) {
            Ext.EventManager.removeResizeListener(this.onWindowResize, this);
        }
        if (this.keyMap) {
            this.keyMap.disable();
        }
        this.onHide();
        this.fireEvent('hide', this);
    },


    animHide: function () {
        this.proxy.setOpacity(0.5);
        this.proxy.show();
        var tb = this.getBox(false);
        this.proxy.setBox(tb);
        this.el.hide();
        this.proxy.shift(Ext.apply(this.animateTarget.getBox(), {
            callback: this.afterHide,
            scope: this,
            duration: this.hideAnimDuration,
            easing: 'easeNone',
            opacity: 0
        }));
    },


    onShow: Ext.emptyFn,


    onHide: Ext.emptyFn,


    onWindowResize: function () {
        if (this.maximized) {
            this.fitContainer();
        }
        if (this.modal) {
            this.mask.setSize('100%', '100%');
            var force = this.mask.dom.offsetHeight;
            this.mask.setSize(Ext.lib.Dom.getViewWidth(true), Ext.lib.Dom.getViewHeight(true));
        }
        this.doConstrain();
    },


    doConstrain: function () {
        if (this.constrain || this.constrainHeader) {
            var offsets;
            if (this.constrain) {
                offsets = {
                    right: this.el.shadowOffset,
                    left: this.el.shadowOffset,
                    bottom: this.el.shadowOffset
                };
            } else {
                var s = this.getSize();
                offsets = {
                    right: -(s.width - 100),
                    bottom: -(s.height - 25)
                };
            }

            var xy = this.el.getConstrainToXY(this.container, true, offsets);
            if (xy) {
                this.setPosition(xy[0], xy[1]);
            }
        }
    },


    ghost: function (cls) {
        var ghost = this.createGhost(cls);
        var box = this.getBox(true);
        ghost.setLeftTop(box.x, box.y);
        ghost.setWidth(box.width);
        this.el.hide();
        this.activeGhost = ghost;
        return ghost;
    },


    unghost: function (show, matchPosition) {
        if (!this.activeGhost) {
            return;
        }
        if (show !== false) {
            this.el.show();
            this.focus.defer(10, this);
            if (Ext.isMac && Ext.isGecko2) {
                this.cascade(this.setAutoScroll);
            }
        }
        if (matchPosition !== false) {
            this.setPosition(this.activeGhost.getLeft(true), this.activeGhost.getTop(true));
        }
        this.activeGhost.hide();
        this.activeGhost.remove();
        delete this.activeGhost;
    },


    minimize: function () {
        this.fireEvent('minimize', this);
        return this;
    },


    close: function () {
        if (this.fireEvent('beforeclose', this) !== false) {
            if (this.hidden) {
                this.doClose();
            } else {
                this.hide(null, this.doClose, this);
            }
        }
    },


    doClose: function () {
        this.fireEvent('close', this);
        this.destroy();
    },


    maximize: function () {
        if (!this.maximized) {
            this.expand(false);
            this.restoreSize = this.getSize();
            this.restorePos = this.getPosition(true);
            if (this.maximizable) {
                this.tools.maximize.hide();
                this.tools.restore.show();
            }
            this.maximized = true;
            this.el.disableShadow();

            if (this.dd) {
                this.dd.lock();
            }
            if (this.collapsible) {
                this.tools.toggle.hide();
            }
            this.el.addClass('x-window-maximized');
            this.container.addClass('x-window-maximized-ct');

            this.setPosition(0, 0);
            this.fitContainer();
            this.fireEvent('maximize', this);
        }
        return this;
    },


    restore: function () {
        if (this.maximized) {
            var t = this.tools;
            this.el.removeClass('x-window-maximized');
            if (t.restore) {
                t.restore.hide();
            }
            if (t.maximize) {
                t.maximize.show();
            }
            this.setPosition(this.restorePos[0], this.restorePos[1]);
            this.setSize(this.restoreSize.width, this.restoreSize.height);
            delete this.restorePos;
            delete this.restoreSize;
            this.maximized = false;
            this.el.enableShadow(true);

            if (this.dd) {
                this.dd.unlock();
            }
            if (this.collapsible && t.toggle) {
                t.toggle.show();
            }
            this.container.removeClass('x-window-maximized-ct');

            this.doConstrain();
            this.fireEvent('restore', this);
        }
        return this;
    },


    toggleMaximize: function () {
        return this[this.maximized ? 'restore' : 'maximize']();
    },


    fitContainer: function () {
        var vs = this.container.getViewSize(false);
        this.setSize(vs.width, vs.height);
    },



    setZIndex: function (index) {
        if (this.modal) {
            this.mask.setStyle('z-index', index);
        }
        this.el.setZIndex(++index);
        index += 5;

        if (this.resizer) {
            this.resizer.proxy.setStyle('z-index', ++index);
        }

        this.lastZIndex = index;
    },


    alignTo: function (element, position, offsets) {
        var xy = this.el.getAlignToXY(element, position, offsets);
        this.setPagePosition(xy[0], xy[1]);
        return this;
    },


    anchorTo: function (el, alignment, offsets, monitorScroll) {
        this.clearAnchor();
        this.anchorTarget = {
            el: el,
            alignment: alignment,
            offsets: offsets
        };

        Ext.EventManager.onWindowResize(this.doAnchor, this);
        var tm = typeof monitorScroll;
        if (tm != 'undefined') {
            Ext.EventManager.on(window, 'scroll', this.doAnchor, this,
                { buffer: tm == 'number' ? monitorScroll : 50 });
        }
        return this.doAnchor();
    },


    doAnchor: function () {
        var o = this.anchorTarget;
        this.alignTo(o.el, o.alignment, o.offsets);
        return this;
    },


    clearAnchor: function () {
        if (this.anchorTarget) {
            Ext.EventManager.removeResizeListener(this.doAnchor, this);
            Ext.EventManager.un(window, 'scroll', this.doAnchor, this);
            delete this.anchorTarget;
        }
        return this;
    },


    toFront: function (e) {
        if (this.manager.bringToFront(this)) {
            if (!e || !e.getTarget().focus) {
                this.focus();
            }
        }
        return this;
    },


    setActive: function (active) {
        if (active) {
            if (!this.maximized) {
                this.el.enableShadow(true);
            }
            this.fireEvent('activate', this);
        } else {
            this.el.disableShadow();
            this.fireEvent('deactivate', this);
        }
    },


    toBack: function () {
        this.manager.sendToBack(this);
        return this;
    },


    center: function () {
        var xy = this.el.getAlignToXY(this.container, 'c-c');
        this.setPagePosition(xy[0], xy[1]);
        return this;
    }


});
Ext.reg('window', Ext.Window);


Ext.Window.DD = Ext.extend(Ext.dd.DD, {

    constructor: function (win) {
        this.win = win;
        Ext.Window.DD.superclass.constructor.call(this, win.el.id, 'WindowDD-' + win.id);
        this.setHandleElId(win.header.id);
        this.scroll = false;
    },

    moveOnly: true,
    headerOffsets: [100, 25],
    startDrag: function () {
        var w = this.win;
        this.proxy = w.ghost(w.initialConfig.cls);
        if (w.constrain !== false) {
            var so = w.el.shadowOffset;
            this.constrainTo(w.container, { right: so, left: so, bottom: so });
        } else if (w.constrainHeader !== false) {
            var s = this.proxy.getSize();
            this.constrainTo(w.container, { right: -(s.width - this.headerOffsets[0]), bottom: -(s.height - this.headerOffsets[1]) });
        }
    },
    b4Drag: Ext.emptyFn,

    onDrag: function (e) {
        this.alignElWithMouse(this.proxy, e.getPageX(), e.getPageY());
    },

    endDrag: function (e) {
        this.win.unghost();
        this.win.saveState();
    }
});

Ext.WindowGroup = function () {
    var list = {};
    var accessList = [];
    var front = null;


    var sortWindows = function (d1, d2) {
        return (!d1._lastAccess || d1._lastAccess < d2._lastAccess) ? -1 : 1;
    };


    var orderWindows = function () {
        var a = accessList, len = a.length;
        if (len > 0) {
            a.sort(sortWindows);
            var seed = a[0].manager.zseed;
            for (var i = 0; i < len; i++) {
                var win = a[i];
                if (win && !win.hidden) {
                    win.setZIndex(seed + (i * 10));
                }
            }
        }
        activateLast();
    };


    var setActiveWin = function (win) {
        if (win != front) {
            if (front) {
                front.setActive(false);
            }
            front = win;
            if (win) {
                win.setActive(true);
            }
        }
    };


    var activateLast = function () {
        for (var i = accessList.length - 1; i >= 0; --i) {
            if (!accessList[i].hidden) {
                setActiveWin(accessList[i]);
                return;
            }
        }

        setActiveWin(null);
    };

    return {

        zseed: 9000,


        register: function (win) {
            if (win.manager) {
                win.manager.unregister(win);
            }
            win.manager = this;

            list[win.id] = win;
            accessList.push(win);
            win.on('hide', activateLast);
        },


        unregister: function (win) {
            delete win.manager;
            delete list[win.id];
            win.un('hide', activateLast);
            accessList.remove(win);
        },


        get: function (id) {
            return typeof id == "object" ? id : list[id];
        },


        bringToFront: function (win) {
            win = this.get(win);
            if (win != front) {
                win._lastAccess = new Date().getTime();
                orderWindows();
                return true;
            }
            return false;
        },


        sendToBack: function (win) {
            win = this.get(win);
            win._lastAccess = -(new Date().getTime());
            orderWindows();
            return win;
        },


        hideAll: function () {
            for (var id in list) {
                if (list[id] && typeof list[id] != "function" && list[id].isVisible()) {
                    list[id].hide();
                }
            }
        },


        getActive: function () {
            return front;
        },


        getBy: function (fn, scope) {
            var r = [];
            for (var i = accessList.length - 1; i >= 0; --i) {
                var win = accessList[i];
                if (fn.call(scope || win, win) !== false) {
                    r.push(win);
                }
            }
            return r;
        },


        each: function (fn, scope) {
            for (var id in list) {
                if (list[id] && typeof list[id] != "function") {
                    if (fn.call(scope || list[id], list[id]) === false) {
                        return;
                    }
                }
            }
        }
    };
};



Ext.WindowMgr = new Ext.WindowGroup();
Ext.MessageBox = function () {
    var dlg, opt, mask, waitTimer,
        bodyEl, msgEl, textboxEl, textareaEl, progressBar, pp, iconEl, spacerEl,
        buttons, activeTextEl, bwidth, bufferIcon = '', iconCls = '',
        buttonNames = ['ok', 'yes', 'no', 'cancel'];


    var handleButton = function (button) {
        buttons[button].blur();
        if (dlg.isVisible()) {
            dlg.hide();
            handleHide();
            Ext.callback(opt.fn, opt.scope || window, [button, activeTextEl.dom.value, opt], 1);
        }
    };


    var handleHide = function () {
        if (opt && opt.cls) {
            dlg.el.removeClass(opt.cls);
        }
        progressBar.reset();
    };


    var handleEsc = function (d, k, e) {
        if (opt && opt.closable !== false) {
            dlg.hide();
            handleHide();
        }
        if (e) {
            e.stopEvent();
        }
    };


    var updateButtons = function (b) {
        var width = 0,
            cfg;
        if (!b) {
            Ext.each(buttonNames, function (name) {
                buttons[name].hide();
            });
            return width;
        }
        dlg.footer.dom.style.display = '';
        Ext.iterate(buttons, function (name, btn) {
            cfg = b[name];
            if (cfg) {
                btn.show();
                btn.setText(Ext.isString(cfg) ? cfg : Ext.MessageBox.buttonText[name]);
                width += btn.getEl().getWidth() + 15;
            } else {
                btn.hide();
            }
        });
        return width;
    };

    return {

        getDialog: function (titleText) {
            if (!dlg) {
                var btns = [];

                buttons = {};
                Ext.each(buttonNames, function (name) {
                    btns.push(buttons[name] = new Ext.Button({
                        text: this.buttonText[name],
                        handler: handleButton.createCallback(name),
                        hideMode: 'offsets'
                    }));
                }, this);
                dlg = new Ext.Window({
                    autoCreate: true,
                    title: titleText,
                    resizable: false,
                    constrain: true,
                    constrainHeader: true,
                    minimizable: false,
                    maximizable: false,
                    stateful: false,
                    modal: true,
                    shim: true,
                    buttonAlign: "center",
                    width: 400,
                    height: 100,
                    minHeight: 80,
                    plain: true,
                    footer: true,
                    closable: true,
                    close: function () {
                        if (opt && opt.buttons && opt.buttons.no && !opt.buttons.cancel) {
                            handleButton("no");
                        } else {
                            handleButton("cancel");
                        }
                    },
                    fbar: new Ext.Toolbar({
                        items: btns,
                        enableOverflow: false
                    })
                });
                dlg.render(document.body);
                dlg.getEl().addClass('x-window-dlg');
                mask = dlg.mask;
                bodyEl = dlg.body.createChild({
                    html: '<div class="ext-mb-icon"></div><div class="ext-mb-content"><span class="ext-mb-text"></span><br /><div class="ext-mb-fix-cursor"><input type="text" class="ext-mb-input" /><textarea class="ext-mb-textarea"></textarea></div></div>'
                });
                iconEl = Ext.get(bodyEl.dom.firstChild);
                var contentEl = bodyEl.dom.childNodes[1];
                msgEl = Ext.get(contentEl.firstChild);
                textboxEl = Ext.get(contentEl.childNodes[2].firstChild);
                textboxEl.enableDisplayMode();
                textboxEl.addKeyListener([10, 13], function () {
                    if (dlg.isVisible() && opt && opt.buttons) {
                        if (opt.buttons.ok) {
                            handleButton("ok");
                        } else if (opt.buttons.yes) {
                            handleButton("yes");
                        }
                    }
                });
                textareaEl = Ext.get(contentEl.childNodes[2].childNodes[1]);
                textareaEl.enableDisplayMode();
                progressBar = new Ext.ProgressBar({
                    renderTo: bodyEl
                });
                bodyEl.createChild({ cls: 'x-clear' });
            }
            return dlg;
        },


        updateText: function (text) {
            if (!dlg.isVisible() && !opt.width) {
                dlg.setSize(this.maxWidth, 100);
            }

            msgEl.update(text ? text + ' ' : '&#160;');

            var iw = iconCls != '' ? (iconEl.getWidth() + iconEl.getMargins('lr')) : 0,
                mw = msgEl.getWidth() + msgEl.getMargins('lr'),
                fw = dlg.getFrameWidth('lr'),
                bw = dlg.body.getFrameWidth('lr'),
                w;

            w = Math.max(Math.min(opt.width || iw + mw + fw + bw, opt.maxWidth || this.maxWidth),
                    Math.max(opt.minWidth || this.minWidth, bwidth || 0));

            if (opt.prompt === true) {
                activeTextEl.setWidth(w - iw - fw - bw);
            }
            if (opt.progress === true || opt.wait === true) {
                progressBar.setSize(w - iw - fw - bw);
            }
            if (Ext.isIE && w == bwidth) {
                w += 4;
            }
            msgEl.update(text || '&#160;');
            dlg.setSize(w, 'auto').center();
            return this;
        },


        updateProgress: function (value, progressText, msg) {
            progressBar.updateProgress(value, progressText);
            if (msg) {
                this.updateText(msg);
            }
            return this;
        },


        isVisible: function () {
            return dlg && dlg.isVisible();
        },


        hide: function () {
            var proxy = dlg ? dlg.activeGhost : null;
            if (this.isVisible() || proxy) {
                dlg.hide();
                handleHide();
                if (proxy) {


                    dlg.unghost(false, false);
                }
            }
            return this;
        },


        show: function (options) {
            if (this.isVisible()) {
                this.hide();
            }
            opt = options;
            var d = this.getDialog(opt.title || "&#160;");

            d.setTitle(opt.title || "&#160;");
            var allowClose = (opt.closable !== false && opt.progress !== true && opt.wait !== true);
            d.tools.close.setDisplayed(allowClose);
            activeTextEl = textboxEl;
            opt.prompt = opt.prompt || (opt.multiline ? true : false);
            if (opt.prompt) {
                if (opt.multiline) {
                    textboxEl.hide();
                    textareaEl.show();
                    textareaEl.setHeight(Ext.isNumber(opt.multiline) ? opt.multiline : this.defaultTextHeight);
                    activeTextEl = textareaEl;
                } else {
                    textboxEl.show();
                    textareaEl.hide();
                }
            } else {
                textboxEl.hide();
                textareaEl.hide();
            }
            activeTextEl.dom.value = opt.value || "";
            if (opt.prompt) {
                d.focusEl = activeTextEl;
            } else {
                var bs = opt.buttons;
                var db = null;
                if (bs && bs.ok) {
                    db = buttons["ok"];
                } else if (bs && bs.yes) {
                    db = buttons["yes"];
                }
                if (db) {
                    d.focusEl = db;
                }
            }
            if (Ext.isDefined(opt.iconCls)) {
                d.setIconClass(opt.iconCls);
            }
            this.setIcon(Ext.isDefined(opt.icon) ? opt.icon : bufferIcon);
            bwidth = updateButtons(opt.buttons);
            progressBar.setVisible(opt.progress === true || opt.wait === true);
            this.updateProgress(0, opt.progressText);
            this.updateText(opt.msg);
            if (opt.cls) {
                d.el.addClass(opt.cls);
            }
            d.proxyDrag = opt.proxyDrag === true;
            d.modal = opt.modal !== false;
            d.mask = opt.modal !== false ? mask : false;
            if (!d.isVisible()) {

                document.body.appendChild(dlg.el.dom);
                d.setAnimateTarget(opt.animEl);

                d.on('show', function () {
                    if (allowClose === true) {
                        d.keyMap.enable();
                    } else {
                        d.keyMap.disable();
                    }
                }, this, { single: true });
                d.show(opt.animEl);
            }
            if (opt.wait === true) {
                progressBar.wait(opt.waitConfig);
            }
            return this;
        },


        setIcon: function (icon) {
            if (!dlg) {
                bufferIcon = icon;
                return;
            }
            bufferIcon = undefined;
            if (icon && icon != '') {
                iconEl.removeClass('x-hidden');
                iconEl.replaceClass(iconCls, icon);
                bodyEl.addClass('x-dlg-icon');
                iconCls = icon;
            } else {
                iconEl.replaceClass(iconCls, 'x-hidden');
                bodyEl.removeClass('x-dlg-icon');
                iconCls = '';
            }
            return this;
        },


        progress: function (title, msg, progressText) {
            this.show({
                title: title,
                msg: msg,
                buttons: false,
                progress: true,
                closable: false,
                minWidth: this.minProgressWidth,
                progressText: progressText
            });
            return this;
        },


        wait: function (msg, title, config) {
            this.show({
                title: title,
                msg: msg,
                buttons: false,
                closable: false,
                wait: true,
                modal: true,
                minWidth: this.minProgressWidth,
                waitConfig: config
            });
            return this;
        },


        alert: function (title, msg, fn, scope) {
            this.show({
                title: title,
                msg: msg,
                buttons: this.OK,
                fn: fn,
                scope: scope,
                minWidth: this.minWidth
            });
            return this;
        },


        confirm: function (title, msg, fn, scope) {
            this.show({
                title: title,
                msg: msg,
                buttons: this.YESNO,
                fn: fn,
                scope: scope,
                icon: this.QUESTION,
                minWidth: this.minWidth
            });
            return this;
        },


        prompt: function (title, msg, fn, scope, multiline, value) {
            this.show({
                title: title,
                msg: msg,
                buttons: this.OKCANCEL,
                fn: fn,
                minWidth: this.minPromptWidth,
                scope: scope,
                prompt: true,
                multiline: multiline,
                value: value
            });
            return this;
        },


        OK: { ok: true },

        CANCEL: { cancel: true },

        OKCANCEL: { ok: true, cancel: true },

        YESNO: { yes: true, no: true },

        YESNOCANCEL: { yes: true, no: true, cancel: true },

        INFO: 'ext-mb-info',

        WARNING: 'ext-mb-warning',

        QUESTION: 'ext-mb-question',

        ERROR: 'ext-mb-error',


        defaultTextHeight: 75,

        maxWidth: 600,

        minWidth: 100,

        minProgressWidth: 250,

        minPromptWidth: 250,

        buttonText: {
            ok: "OK",
            cancel: "Cancel",
            yes: "Yes",
            no: "No"
        }
    };
} ();


Ext.Msg = Ext.MessageBox;
Ext.dd.PanelProxy = Ext.extend(Object, {

    constructor: function (panel, config) {
        this.panel = panel;
        this.id = this.panel.id + '-ddproxy';
        Ext.apply(this, config);
    },


    insertProxy: true,


    setStatus: Ext.emptyFn,
    reset: Ext.emptyFn,
    update: Ext.emptyFn,
    stop: Ext.emptyFn,
    sync: Ext.emptyFn,


    getEl: function () {
        return this.ghost;
    },


    getGhost: function () {
        return this.ghost;
    },


    getProxy: function () {
        return this.proxy;
    },


    hide: function () {
        if (this.ghost) {
            if (this.proxy) {
                this.proxy.remove();
                delete this.proxy;
            }
            this.panel.el.dom.style.display = '';
            this.ghost.remove();
            delete this.ghost;
        }
    },


    show: function () {
        if (!this.ghost) {
            this.ghost = this.panel.createGhost(this.panel.initialConfig.cls, undefined, Ext.getBody());
            this.ghost.setXY(this.panel.el.getXY());
            if (this.insertProxy) {
                this.proxy = this.panel.el.insertSibling({ cls: 'x-panel-dd-spacer' });
                this.proxy.setSize(this.panel.getSize());
            }
            this.panel.el.dom.style.display = 'none';
        }
    },


    repair: function (xy, callback, scope) {
        this.hide();
        if (typeof callback == "function") {
            callback.call(scope || this);
        }
    },


    moveProxy: function (parentNode, before) {
        if (this.proxy) {
            parentNode.insertBefore(this.proxy.dom, before);
        }
    }
});


Ext.Panel.DD = Ext.extend(Ext.dd.DragSource, {

    constructor: function (panel, cfg) {
        this.panel = panel;
        this.dragData = { panel: panel };
        this.proxy = new Ext.dd.PanelProxy(panel, cfg);
        Ext.Panel.DD.superclass.constructor.call(this, panel.el, cfg);
        var h = panel.header,
            el = panel.body;
        if (h) {
            this.setHandleElId(h.id);
            el = panel.header;
        }
        el.setStyle('cursor', 'move');
        this.scroll = false;
    },

    showFrame: Ext.emptyFn,
    startDrag: Ext.emptyFn,
    b4StartDrag: function (x, y) {
        this.proxy.show();
    },
    b4MouseDown: function (e) {
        var x = e.getPageX(),
            y = e.getPageY();
        this.autoOffset(x, y);
    },
    onInitDrag: function (x, y) {
        this.onStartDrag(x, y);
        return true;
    },
    createFrame: Ext.emptyFn,
    getDragEl: function (e) {
        return this.proxy.ghost.dom;
    },
    endDrag: function (e) {
        this.proxy.hide();
        this.panel.saveState();
    },

    autoOffset: function (x, y) {
        x -= this.startPageX;
        y -= this.startPageY;
        this.setDelta(x, y);
    }
});
Ext.state.Provider = Ext.extend(Ext.util.Observable, {

    constructor: function () {

        this.addEvents("statechange");
        this.state = {};
        Ext.state.Provider.superclass.constructor.call(this);
    },


    get: function (name, defaultValue) {
        return typeof this.state[name] == "undefined" ?
            defaultValue : this.state[name];
    },


    clear: function (name) {
        delete this.state[name];
        this.fireEvent("statechange", this, name, null);
    },


    set: function (name, value) {
        this.state[name] = value;
        this.fireEvent("statechange", this, name, value);
    },


    decodeValue: function (cookie) {

        var re = /^(a|n|d|b|s|o|e)\:(.*)$/,
            matches = re.exec(unescape(cookie)),
            all,
            type,
            v,
            kv;
        if (!matches || !matches[1]) {
            return;
        }
        type = matches[1];
        v = matches[2];
        switch (type) {
            case 'e':
                return null;
            case 'n':
                return parseFloat(v);
            case 'd':
                return new Date(Date.parse(v));
            case 'b':
                return (v == '1');
            case 'a':
                all = [];
                if (v != '') {
                    Ext.each(v.split('^'), function (val) {
                        all.push(this.decodeValue(val));
                    }, this);
                }
                return all;
            case 'o':
                all = {};
                if (v != '') {
                    Ext.each(v.split('^'), function (val) {
                        kv = val.split('=');
                        all[kv[0]] = this.decodeValue(kv[1]);
                    }, this);
                }
                return all;
            default:
                return v;
        }
    },


    encodeValue: function (v) {
        var enc,
            flat = '',
            i = 0,
            len,
            key;
        if (v == null) {
            return 'e:1';
        } else if (typeof v == 'number') {
            enc = 'n:' + v;
        } else if (typeof v == 'boolean') {
            enc = 'b:' + (v ? '1' : '0');
        } else if (Ext.isDate(v)) {
            enc = 'd:' + v.toGMTString();
        } else if (Ext.isArray(v)) {
            for (len = v.length; i < len; i++) {
                flat += this.encodeValue(v[i]);
                if (i != len - 1) {
                    flat += '^';
                }
            }
            enc = 'a:' + flat;
        } else if (typeof v == 'object') {
            for (key in v) {
                if (typeof v[key] != 'function' && v[key] !== undefined) {
                    flat += key + '=' + this.encodeValue(v[key]) + '^';
                }
            }
            enc = 'o:' + flat.substring(0, flat.length - 1);
        } else {
            enc = 's:' + v;
        }
        return escape(enc);
    }
});

Ext.state.Manager = function () {
    var provider = new Ext.state.Provider();

    return {

        setProvider: function (stateProvider) {
            provider = stateProvider;
        },


        get: function (key, defaultValue) {
            return provider.get(key, defaultValue);
        },


        set: function (key, value) {
            provider.set(key, value);
        },


        clear: function (key) {
            provider.clear(key);
        },


        getProvider: function () {
            return provider;
        }
    };
} ();

Ext.state.CookieProvider = Ext.extend(Ext.state.Provider, {

    constructor: function (config) {
        Ext.state.CookieProvider.superclass.constructor.call(this);
        this.path = "/";
        this.expires = new Date(new Date().getTime() + (1000 * 60 * 60 * 24 * 7));
        this.domain = null;
        this.secure = false;
        Ext.apply(this, config);
        this.state = this.readCookies();
    },


    set: function (name, value) {
        if (typeof value == "undefined" || value === null) {
            this.clear(name);
            return;
        }
        this.setCookie(name, value);
        Ext.state.CookieProvider.superclass.set.call(this, name, value);
    },


    clear: function (name) {
        this.clearCookie(name);
        Ext.state.CookieProvider.superclass.clear.call(this, name);
    },


    readCookies: function () {
        var cookies = {},
            c = document.cookie + ";",
            re = /\s?(.*?)=(.*?);/g,
    	    matches,
            name,
            value;
        while ((matches = re.exec(c)) != null) {
            name = matches[1];
            value = matches[2];
            if (name && name.substring(0, 3) == "ys-") {
                cookies[name.substr(3)] = this.decodeValue(value);
            }
        }
        return cookies;
    },


    setCookie: function (name, value) {
        document.cookie = "ys-" + name + "=" + this.encodeValue(value) +
           ((this.expires == null) ? "" : ("; expires=" + this.expires.toGMTString())) +
           ((this.path == null) ? "" : ("; path=" + this.path)) +
           ((this.domain == null) ? "" : ("; domain=" + this.domain)) +
           ((this.secure == true) ? "; secure" : "");
    },


    clearCookie: function (name) {
        document.cookie = "ys-" + name + "=null; expires=Thu, 01-Jan-70 00:00:01 GMT" +
           ((this.path == null) ? "" : ("; path=" + this.path)) +
           ((this.domain == null) ? "" : ("; domain=" + this.domain)) +
           ((this.secure == true) ? "; secure" : "");
    }
});
Ext.DataView = Ext.extend(Ext.BoxComponent, {









    selectedClass: "x-view-selected",

    emptyText: "",


    deferEmptyText: true,

    trackOver: false,


    blockRefresh: false,


    last: false,


    initComponent: function () {
        Ext.DataView.superclass.initComponent.call(this);
        if (Ext.isString(this.tpl) || Ext.isArray(this.tpl)) {
            this.tpl = new Ext.XTemplate(this.tpl);
        }

        this.addEvents(

            "beforeclick",

            "click",

            "mouseenter",

            "mouseleave",

            "containerclick",

            "dblclick",

            "contextmenu",

            "containercontextmenu",

            "selectionchange",


            "beforeselect"
        );

        this.store = Ext.StoreMgr.lookup(this.store);
        this.all = new Ext.CompositeElementLite();
        this.selected = new Ext.CompositeElementLite();
    },


    afterRender: function () {
        Ext.DataView.superclass.afterRender.call(this);

        this.mon(this.getTemplateTarget(), {
            "click": this.onClick,
            "dblclick": this.onDblClick,
            "contextmenu": this.onContextMenu,
            scope: this
        });

        if (this.overClass || this.trackOver) {
            this.mon(this.getTemplateTarget(), {
                "mouseover": this.onMouseOver,
                "mouseout": this.onMouseOut,
                scope: this
            });
        }

        if (this.store) {
            this.bindStore(this.store, true);
        }
    },


    refresh: function () {
        this.clearSelections(false, true);
        var el = this.getTemplateTarget(),
            records = this.store.getRange();

        el.update('');
        if (records.length < 1) {
            if (!this.deferEmptyText || this.hasSkippedEmptyText) {
                el.update(this.emptyText);
            }
            this.all.clear();
        } else {
            this.tpl.overwrite(el, this.collectData(records, 0));
            this.all.fill(Ext.query(this.itemSelector, el.dom));
            this.updateIndexes(0);
        }
        this.hasSkippedEmptyText = true;
    },

    getTemplateTarget: function () {
        return this.el;
    },


    prepareData: function (data) {
        return data;
    },


    collectData: function (records, startIndex) {
        var r = [],
            i = 0,
            len = records.length;
        for (; i < len; i++) {
            r[r.length] = this.prepareData(records[i].data, startIndex + i, records[i]);
        }
        return r;
    },


    bufferRender: function (records, index) {
        var div = document.createElement('div');
        this.tpl.overwrite(div, this.collectData(records, index));
        return Ext.query(this.itemSelector, div);
    },


    onUpdate: function (ds, record) {
        var index = this.store.indexOf(record);
        if (index > -1) {
            var sel = this.isSelected(index),
                original = this.all.elements[index],
                node = this.bufferRender([record], index)[0];

            this.all.replaceElement(index, node, true);
            if (sel) {
                this.selected.replaceElement(original, node);
                this.all.item(index).addClass(this.selectedClass);
            }
            this.updateIndexes(index, index);
        }
    },


    onAdd: function (ds, records, index) {
        if (this.all.getCount() === 0) {
            this.refresh();
            return;
        }
        var nodes = this.bufferRender(records, index), n, a = this.all.elements;
        if (index < this.all.getCount()) {
            n = this.all.item(index).insertSibling(nodes, 'before', true);
            a.splice.apply(a, [index, 0].concat(nodes));
        } else {
            n = this.all.last().insertSibling(nodes, 'after', true);
            a.push.apply(a, nodes);
        }
        this.updateIndexes(index);
    },


    onRemove: function (ds, record, index) {
        this.deselect(index);
        this.all.removeElement(index, true);
        this.updateIndexes(index);
        if (this.store.getCount() === 0) {
            this.refresh();
        }
    },


    refreshNode: function (index) {
        this.onUpdate(this.store, this.store.getAt(index));
    },


    updateIndexes: function (startIndex, endIndex) {
        var ns = this.all.elements;
        startIndex = startIndex || 0;
        endIndex = endIndex || ((endIndex === 0) ? 0 : (ns.length - 1));
        for (var i = startIndex; i <= endIndex; i++) {
            ns[i].viewIndex = i;
        }
    },


    getStore: function () {
        return this.store;
    },


    bindStore: function (store, initial) {
        if (!initial && this.store) {
            if (store !== this.store && this.store.autoDestroy) {
                this.store.destroy();
            } else {
                this.store.un("beforeload", this.onBeforeLoad, this);
                this.store.un("datachanged", this.onDataChanged, this);
                this.store.un("add", this.onAdd, this);
                this.store.un("remove", this.onRemove, this);
                this.store.un("update", this.onUpdate, this);
                this.store.un("clear", this.refresh, this);
            }
            if (!store) {
                this.store = null;
            }
        }
        if (store) {
            store = Ext.StoreMgr.lookup(store);
            store.on({
                scope: this,
                beforeload: this.onBeforeLoad,
                datachanged: this.onDataChanged,
                add: this.onAdd,
                remove: this.onRemove,
                update: this.onUpdate,
                clear: this.refresh
            });
        }
        this.store = store;
        if (store) {
            this.refresh();
        }
    },


    onDataChanged: function () {
        if (this.blockRefresh !== true) {
            this.refresh.apply(this, arguments);
        }
    },


    findItemFromChild: function (node) {
        return Ext.fly(node).findParent(this.itemSelector, this.getTemplateTarget());
    },


    onClick: function (e) {
        var item = e.getTarget(this.itemSelector, this.getTemplateTarget()),
            index;
        if (item) {
            index = this.indexOf(item);
            if (this.onItemClick(item, index, e) !== false) {
                this.fireEvent("click", this, index, item, e);
            }
        } else {
            if (this.fireEvent("containerclick", this, e) !== false) {
                this.onContainerClick(e);
            }
        }
    },

    onContainerClick: function (e) {
        this.clearSelections();
    },


    onContextMenu: function (e) {
        var item = e.getTarget(this.itemSelector, this.getTemplateTarget());
        if (item) {
            this.fireEvent("contextmenu", this, this.indexOf(item), item, e);
        } else {
            this.fireEvent("containercontextmenu", this, e);
        }
    },


    onDblClick: function (e) {
        var item = e.getTarget(this.itemSelector, this.getTemplateTarget());
        if (item) {
            this.fireEvent("dblclick", this, this.indexOf(item), item, e);
        }
    },


    onMouseOver: function (e) {
        var item = e.getTarget(this.itemSelector, this.getTemplateTarget());
        if (item && item !== this.lastItem) {
            this.lastItem = item;
            Ext.fly(item).addClass(this.overClass);
            this.fireEvent("mouseenter", this, this.indexOf(item), item, e);
        }
    },


    onMouseOut: function (e) {
        if (this.lastItem) {
            if (!e.within(this.lastItem, true, true)) {
                Ext.fly(this.lastItem).removeClass(this.overClass);
                this.fireEvent("mouseleave", this, this.indexOf(this.lastItem), this.lastItem, e);
                delete this.lastItem;
            }
        }
    },


    onItemClick: function (item, index, e) {
        if (this.fireEvent("beforeclick", this, index, item, e) === false) {
            return false;
        }
        if (this.multiSelect) {
            this.doMultiSelection(item, index, e);
            e.preventDefault();
        } else if (this.singleSelect) {
            this.doSingleSelection(item, index, e);
            e.preventDefault();
        }
        return true;
    },


    doSingleSelection: function (item, index, e) {
        if (e.ctrlKey && this.isSelected(index)) {
            this.deselect(index);
        } else {
            this.select(index, false);
        }
    },


    doMultiSelection: function (item, index, e) {
        if (e.shiftKey && this.last !== false) {
            var last = this.last;
            this.selectRange(last, index, e.ctrlKey);
            this.last = last;
        } else {
            if ((e.ctrlKey || this.simpleSelect) && this.isSelected(index)) {
                this.deselect(index);
            } else {
                this.select(index, e.ctrlKey || e.shiftKey || this.simpleSelect);
            }
        }
    },


    getSelectionCount: function () {
        return this.selected.getCount();
    },


    getSelectedNodes: function () {
        return this.selected.elements;
    },


    getSelectedIndexes: function () {
        var indexes = [],
            selected = this.selected.elements,
            i = 0,
            len = selected.length;

        for (; i < len; i++) {
            indexes.push(selected[i].viewIndex);
        }
        return indexes;
    },


    getSelectedRecords: function () {
        return this.getRecords(this.selected.elements);
    },


    getRecords: function (nodes) {
        var records = [],
            i = 0,
            len = nodes.length;

        for (; i < len; i++) {
            records[records.length] = this.store.getAt(nodes[i].viewIndex);
        }
        return records;
    },


    getRecord: function (node) {
        return this.store.getAt(node.viewIndex);
    },


    clearSelections: function (suppressEvent, skipUpdate) {
        if ((this.multiSelect || this.singleSelect) && this.selected.getCount() > 0) {
            if (!skipUpdate) {
                this.selected.removeClass(this.selectedClass);
            }
            this.selected.clear();
            this.last = false;
            if (!suppressEvent) {
                this.fireEvent("selectionchange", this, this.selected.elements);
            }
        }
    },


    isSelected: function (node) {
        return this.selected.contains(this.getNode(node));
    },


    deselect: function (node) {
        if (this.isSelected(node)) {
            node = this.getNode(node);
            this.selected.removeElement(node);
            if (this.last == node.viewIndex) {
                this.last = false;
            }
            Ext.fly(node).removeClass(this.selectedClass);
            this.fireEvent("selectionchange", this, this.selected.elements);
        }
    },


    select: function (nodeInfo, keepExisting, suppressEvent) {
        if (Ext.isArray(nodeInfo)) {
            if (!keepExisting) {
                this.clearSelections(true);
            }
            for (var i = 0, len = nodeInfo.length; i < len; i++) {
                this.select(nodeInfo[i], true, true);
            }
            if (!suppressEvent) {
                this.fireEvent("selectionchange", this, this.selected.elements);
            }
        } else {
            var node = this.getNode(nodeInfo);
            if (!keepExisting) {
                this.clearSelections(true);
            }
            if (node && !this.isSelected(node)) {
                if (this.fireEvent("beforeselect", this, node, this.selected.elements) !== false) {
                    Ext.fly(node).addClass(this.selectedClass);
                    this.selected.add(node);
                    this.last = node.viewIndex;
                    if (!suppressEvent) {
                        this.fireEvent("selectionchange", this, this.selected.elements);
                    }
                }
            }
        }
    },


    selectRange: function (start, end, keepExisting) {
        if (!keepExisting) {
            this.clearSelections(true);
        }
        this.select(this.getNodes(start, end), true);
    },


    getNode: function (nodeInfo) {
        if (Ext.isString(nodeInfo)) {
            return document.getElementById(nodeInfo);
        } else if (Ext.isNumber(nodeInfo)) {
            return this.all.elements[nodeInfo];
        } else if (nodeInfo instanceof Ext.data.Record) {
            var idx = this.store.indexOf(nodeInfo);
            return this.all.elements[idx];
        }
        return nodeInfo;
    },


    getNodes: function (start, end) {
        var ns = this.all.elements,
            nodes = [],
            i;

        start = start || 0;
        end = !Ext.isDefined(end) ? Math.max(ns.length - 1, 0) : end;
        if (start <= end) {
            for (i = start; i <= end && ns[i]; i++) {
                nodes.push(ns[i]);
            }
        } else {
            for (i = start; i >= end && ns[i]; i--) {
                nodes.push(ns[i]);
            }
        }
        return nodes;
    },


    indexOf: function (node) {
        node = this.getNode(node);
        if (Ext.isNumber(node.viewIndex)) {
            return node.viewIndex;
        }
        return this.all.indexOf(node);
    },


    onBeforeLoad: function () {
        if (this.loadingText) {
            this.clearSelections(false, true);
            this.getTemplateTarget().update('<div class="loading-indicator">' + this.loadingText + '</div>');
            this.all.clear();
        }
    },

    onDestroy: function () {
        this.all.clear();
        this.selected.clear();
        Ext.DataView.superclass.onDestroy.call(this);
        this.bindStore(null);
    }
});


Ext.DataView.prototype.setStore = Ext.DataView.prototype.bindStore;

Ext.reg('dataview', Ext.DataView);

Ext.list.ListView = Ext.extend(Ext.DataView, {



    itemSelector: 'dl',

    selectedClass: 'x-list-selected',

    overClass: 'x-list-over',


    scrollOffset: undefined,

    columnResize: true,


    columnSort: true,



    maxColumnWidth: Ext.isIE ? 99 : 100,

    initComponent: function () {
        if (this.columnResize) {
            this.colResizer = new Ext.list.ColumnResizer(this.colResizer);
            this.colResizer.init(this);
        }
        if (this.columnSort) {
            this.colSorter = new Ext.list.Sorter(this.columnSort);
            this.colSorter.init(this);
        }
        if (!this.internalTpl) {
            this.internalTpl = new Ext.XTemplate(
                '<div class="x-list-header"><div class="x-list-header-inner">',
                    '<tpl for="columns">',
                    '<div style="width:{[values.width*100]}%;text-align:{align};"><em unselectable="on" id="', this.id, '-xlhd-{#}">',
                        '{header}',
                    '</em></div>',
                    '</tpl>',
                    '<div class="x-clear"></div>',
                '</div></div>',
                '<div class="x-list-body"><div class="x-list-body-inner">',
                '</div></div>'
            );
        }
        if (!this.tpl) {
            this.tpl = new Ext.XTemplate(
                '<tpl for="rows">',
                    '<dl>',
                        '<tpl for="parent.columns">',
                        '<dt style="width:{[values.width*100]}%;text-align:{align};">',
                        '<em unselectable="on"<tpl if="cls"> class="{cls}</tpl>">',
                            '{[values.tpl.apply(parent)]}',
                        '</em></dt>',
                        '</tpl>',
                        '<div class="x-clear"></div>',
                    '</dl>',
                '</tpl>'
            );
        };

        var cs = this.columns,
            allocatedWidth = 0,
            colsWithWidth = 0,
            len = cs.length,
            columns = [];

        for (var i = 0; i < len; i++) {
            var c = cs[i];
            if (!c.isColumn) {
                c.xtype = c.xtype ? (/^lv/.test(c.xtype) ? c.xtype : 'lv' + c.xtype) : 'lvcolumn';
                c = Ext.create(c);
            }
            if (c.width) {
                allocatedWidth += c.width * 100;
                if (allocatedWidth > this.maxColumnWidth) {
                    c.width -= (allocatedWidth - this.maxColumnWidth) / 100;
                }
                colsWithWidth++;
            }
            columns.push(c);
        }

        cs = this.columns = columns;


        if (colsWithWidth < len) {
            var remaining = len - colsWithWidth;
            if (allocatedWidth < this.maxColumnWidth) {
                var perCol = ((this.maxColumnWidth - allocatedWidth) / remaining) / 100;
                for (var j = 0; j < len; j++) {
                    var c = cs[j];
                    if (!c.width) {
                        c.width = perCol;
                    }
                }
            }
        }
        Ext.list.ListView.superclass.initComponent.call(this);
    },

    onRender: function () {
        this.autoEl = {
            cls: 'x-list-wrap'
        };
        Ext.list.ListView.superclass.onRender.apply(this, arguments);

        this.internalTpl.overwrite(this.el, { columns: this.columns });

        this.innerBody = Ext.get(this.el.dom.childNodes[1].firstChild);
        this.innerHd = Ext.get(this.el.dom.firstChild.firstChild);

        if (this.hideHeaders) {
            this.el.dom.firstChild.style.display = 'none';
        }
    },

    getTemplateTarget: function () {
        return this.innerBody;
    },


    collectData: function () {
        var rs = Ext.list.ListView.superclass.collectData.apply(this, arguments);
        return {
            columns: this.columns,
            rows: rs
        };
    },

    verifyInternalSize: function () {
        if (this.lastSize) {
            this.onResize(this.lastSize.width, this.lastSize.height);
        }
    },


    onResize: function (w, h) {
        var body = this.innerBody.dom,
            header = this.innerHd.dom,
            scrollWidth = w - Ext.num(this.scrollOffset, Ext.getScrollBarWidth()) + 'px',
            parentNode;

        if (!body) {
            return;
        }
        parentNode = body.parentNode;
        if (Ext.isNumber(w)) {
            if (this.reserveScrollOffset || ((parentNode.offsetWidth - parentNode.clientWidth) > 10)) {
                body.style.width = scrollWidth;
                header.style.width = scrollWidth;
            } else {
                body.style.width = w + 'px';
                header.style.width = w + 'px';
                setTimeout(function () {
                    if ((parentNode.offsetWidth - parentNode.clientWidth) > 10) {
                        body.style.width = scrollWidth;
                        header.style.width = scrollWidth;
                    }
                }, 10);
            }
        }
        if (Ext.isNumber(h)) {
            parentNode.style.height = Math.max(0, h - header.parentNode.offsetHeight) + 'px';
        }
    },

    updateIndexes: function () {
        Ext.list.ListView.superclass.updateIndexes.apply(this, arguments);
        this.verifyInternalSize();
    },

    findHeaderIndex: function (header) {
        header = header.dom || header;
        var parentNode = header.parentNode,
            children = parentNode.parentNode.childNodes,
            i = 0,
            c;
        for (; c = children[i]; i++) {
            if (c == parentNode) {
                return i;
            }
        }
        return -1;
    },

    setHdWidths: function () {
        var els = this.innerHd.dom.getElementsByTagName('div'),
            i = 0,
            columns = this.columns,
            len = columns.length;

        for (; i < len; i++) {
            els[i].style.width = (columns[i].width * 100) + '%';
        }
    }
});

Ext.reg('listview', Ext.list.ListView);


Ext.ListView = Ext.list.ListView;
Ext.list.Column = Ext.extend(Object, {

    isColumn: true,


    align: 'left',

    header: '',


    width: null,


    cls: '',





    constructor: function (c) {
        if (!c.tpl) {
            c.tpl = new Ext.XTemplate('{' + c.dataIndex + '}');
        }
        else if (Ext.isString(c.tpl)) {
            c.tpl = new Ext.XTemplate(c.tpl);
        }

        Ext.apply(this, c);
    }
});

Ext.reg('lvcolumn', Ext.list.Column);


Ext.list.NumberColumn = Ext.extend(Ext.list.Column, {

    format: '0,000.00',

    constructor: function (c) {
        c.tpl = c.tpl || new Ext.XTemplate('{' + c.dataIndex + ':number("' + (c.format || this.format) + '")}');
        Ext.list.NumberColumn.superclass.constructor.call(this, c);
    }
});

Ext.reg('lvnumbercolumn', Ext.list.NumberColumn);


Ext.list.DateColumn = Ext.extend(Ext.list.Column, {
    format: 'm/d/Y',
    constructor: function (c) {
        c.tpl = c.tpl || new Ext.XTemplate('{' + c.dataIndex + ':date("' + (c.format || this.format) + '")}');
        Ext.list.DateColumn.superclass.constructor.call(this, c);
    }
});
Ext.reg('lvdatecolumn', Ext.list.DateColumn);


Ext.list.BooleanColumn = Ext.extend(Ext.list.Column, {

    trueText: 'true',

    falseText: 'false',

    undefinedText: '&#160;',

    constructor: function (c) {
        c.tpl = c.tpl || new Ext.XTemplate('{' + c.dataIndex + ':this.format}');

        var t = this.trueText, f = this.falseText, u = this.undefinedText;
        c.tpl.format = function (v) {
            if (v === undefined) {
                return u;
            }
            if (!v || v === 'false') {
                return f;
            }
            return t;
        };

        Ext.list.DateColumn.superclass.constructor.call(this, c);
    }
});

Ext.reg('lvbooleancolumn', Ext.list.BooleanColumn);
Ext.list.ColumnResizer = Ext.extend(Ext.util.Observable, {

    minPct: .05,

    constructor: function (config) {
        Ext.apply(this, config);
        Ext.list.ColumnResizer.superclass.constructor.call(this);
    },
    init: function (listView) {
        this.view = listView;
        listView.on('render', this.initEvents, this);
    },

    initEvents: function (view) {
        view.mon(view.innerHd, 'mousemove', this.handleHdMove, this);
        this.tracker = new Ext.dd.DragTracker({
            onBeforeStart: this.onBeforeStart.createDelegate(this),
            onStart: this.onStart.createDelegate(this),
            onDrag: this.onDrag.createDelegate(this),
            onEnd: this.onEnd.createDelegate(this),
            tolerance: 3,
            autoStart: 300
        });
        this.tracker.initEl(view.innerHd);
        view.on('beforedestroy', this.tracker.destroy, this.tracker);
    },

    handleHdMove: function (e, t) {
        var handleWidth = 5,
            x = e.getPageX(),
            header = e.getTarget('em', 3, true);
        if (header) {
            var region = header.getRegion(),
                style = header.dom.style,
                parentNode = header.dom.parentNode;

            if (x - region.left <= handleWidth && parentNode != parentNode.parentNode.firstChild) {
                this.activeHd = Ext.get(parentNode.previousSibling.firstChild);
                style.cursor = Ext.isWebKit ? 'e-resize' : 'col-resize';
            } else if (region.right - x <= handleWidth && parentNode != parentNode.parentNode.lastChild.previousSibling) {
                this.activeHd = header;
                style.cursor = Ext.isWebKit ? 'w-resize' : 'col-resize';
            } else {
                delete this.activeHd;
                style.cursor = '';
            }
        }
    },

    onBeforeStart: function (e) {
        this.dragHd = this.activeHd;
        return !!this.dragHd;
    },

    onStart: function (e) {

        var me = this,
            view = me.view,
            dragHeader = me.dragHd,
            x = me.tracker.getXY()[0];

        me.proxy = view.el.createChild({ cls: 'x-list-resizer' });
        me.dragX = dragHeader.getX();
        me.headerIndex = view.findHeaderIndex(dragHeader);

        me.headersDisabled = view.disableHeaders;
        view.disableHeaders = true;

        me.proxy.setHeight(view.el.getHeight());
        me.proxy.setX(me.dragX);
        me.proxy.setWidth(x - me.dragX);

        this.setBoundaries();

    },


    setBoundaries: function (relativeX) {
        var view = this.view,
            headerIndex = this.headerIndex,
            width = view.innerHd.getWidth(),
            relativeX = view.innerHd.getX(),
            minWidth = Math.ceil(width * this.minPct),
            maxWidth = width - minWidth,
            numColumns = view.columns.length,
            headers = view.innerHd.select('em', true),
            minX = minWidth + relativeX,
            maxX = maxWidth + relativeX,
            header;

        if (numColumns == 2) {
            this.minX = minX;
            this.maxX = maxX;
        } else {
            header = headers.item(headerIndex + 2);
            this.minX = headers.item(headerIndex).getX() + minWidth;
            this.maxX = header ? header.getX() - minWidth : maxX;
            if (headerIndex == 0) {

                this.minX = minX;
            } else if (headerIndex == numColumns - 2) {

                this.maxX = maxX;
            }
        }
    },

    onDrag: function (e) {
        var me = this,
            cursorX = me.tracker.getXY()[0].constrain(me.minX, me.maxX);

        me.proxy.setWidth(cursorX - this.dragX);
    },

    onEnd: function (e) {

        var newWidth = this.proxy.getWidth(),
            index = this.headerIndex,
            view = this.view,
            columns = view.columns,
            width = view.innerHd.getWidth(),
            newPercent = Math.ceil(newWidth * view.maxColumnWidth / width) / 100,
            disabled = this.headersDisabled,
            headerCol = columns[index],
            otherCol = columns[index + 1],
            totalPercent = headerCol.width + otherCol.width;

        this.proxy.remove();

        headerCol.width = newPercent;
        otherCol.width = totalPercent - newPercent;

        delete this.dragHd;
        view.setHdWidths();
        view.refresh();

        setTimeout(function () {
            view.disableHeaders = disabled;
        }, 100);
    }
});


Ext.ListView.ColumnResizer = Ext.list.ColumnResizer;
Ext.list.Sorter = Ext.extend(Ext.util.Observable, {

    sortClasses: ["sort-asc", "sort-desc"],

    constructor: function (config) {
        Ext.apply(this, config);
        Ext.list.Sorter.superclass.constructor.call(this);
    },

    init: function (listView) {
        this.view = listView;
        listView.on('render', this.initEvents, this);
    },

    initEvents: function (view) {
        view.mon(view.innerHd, 'click', this.onHdClick, this);
        view.innerHd.setStyle('cursor', 'pointer');
        view.mon(view.store, 'datachanged', this.updateSortState, this);
        this.updateSortState.defer(10, this, [view.store]);
    },

    updateSortState: function (store) {
        var state = store.getSortState();
        if (!state) {
            return;
        }
        this.sortState = state;
        var cs = this.view.columns, sortColumn = -1;
        for (var i = 0, len = cs.length; i < len; i++) {
            if (cs[i].dataIndex == state.field) {
                sortColumn = i;
                break;
            }
        }
        if (sortColumn != -1) {
            var sortDir = state.direction;
            this.updateSortIcon(sortColumn, sortDir);
        }
    },

    updateSortIcon: function (col, dir) {
        var sc = this.sortClasses;
        var hds = this.view.innerHd.select('em').removeClass(sc);
        hds.item(col).addClass(sc[dir == "DESC" ? 1 : 0]);
    },

    onHdClick: function (e) {
        var hd = e.getTarget('em', 3);
        if (hd && !this.view.disableHeaders) {
            var index = this.view.findHeaderIndex(hd);
            this.view.store.sort(this.view.columns[index].dataIndex);
        }
    }
});


Ext.ListView.Sorter = Ext.list.Sorter;
Ext.TabPanel = Ext.extend(Ext.Panel, {



    deferredRender: true,

    tabWidth: 120,

    minTabWidth: 30,

    resizeTabs: false,

    enableTabScroll: false,

    scrollIncrement: 0,

    scrollRepeatInterval: 400,

    scrollDuration: 0.35,

    animScroll: true,

    tabPosition: 'top',

    baseCls: 'x-tab-panel',

    autoTabs: false,

    autoTabSelector: 'div.x-tab',

    activeTab: undefined,

    tabMargin: 2,

    plain: false,

    wheelIncrement: 20,


    idDelimiter: '__',


    itemCls: 'x-tab-item',


    elements: 'body',
    headerAsText: false,
    frame: false,
    hideBorders: true,


    initComponent: function () {
        this.frame = false;
        Ext.TabPanel.superclass.initComponent.call(this);
        this.addEvents(

            'beforetabchange',

            'tabchange',

            'contextmenu'
        );

        this.setLayout(new Ext.layout.CardLayout(Ext.apply({
            layoutOnCardChange: this.layoutOnTabChange,
            deferredRender: this.deferredRender
        }, this.layoutConfig)));

        if (this.tabPosition == 'top') {
            this.elements += ',header';
            this.stripTarget = 'header';
        } else {
            this.elements += ',footer';
            this.stripTarget = 'footer';
        }
        if (!this.stack) {
            this.stack = Ext.TabPanel.AccessStack();
        }
        this.initItems();
    },


    onRender: function (ct, position) {
        Ext.TabPanel.superclass.onRender.call(this, ct, position);

        if (this.plain) {
            var pos = this.tabPosition == 'top' ? 'header' : 'footer';
            this[pos].addClass('x-tab-panel-' + pos + '-plain');
        }

        var st = this[this.stripTarget];

        this.stripWrap = st.createChild({ cls: 'x-tab-strip-wrap', cn: {
            tag: 'ul', cls: 'x-tab-strip x-tab-strip-' + this.tabPosition
        }
        });

        var beforeEl = (this.tabPosition == 'bottom' ? this.stripWrap : null);
        st.createChild({ cls: 'x-tab-strip-spacer' }, beforeEl);
        this.strip = new Ext.Element(this.stripWrap.dom.firstChild);


        this.edge = this.strip.createChild({ tag: 'li', cls: 'x-tab-edge', cn: [{ tag: 'span', cls: 'x-tab-strip-text', cn: '&#160;'}] });
        this.strip.createChild({ cls: 'x-clear' });

        this.body.addClass('x-tab-panel-body-' + this.tabPosition);


        if (!this.itemTpl) {
            var tt = new Ext.Template(
                 '<li class="{cls}" id="{id}"><a class="x-tab-strip-close"></a>',
                 '<a class="x-tab-right" href="#"><em class="x-tab-left">',
                 '<span class="x-tab-strip-inner"><span class="x-tab-strip-text {iconCls}">{text}</span></span>',
                 '</em></a></li>'
            );
            tt.disableFormats = true;
            tt.compile();
            Ext.TabPanel.prototype.itemTpl = tt;
        }

        this.items.each(this.initTab, this);
    },


    afterRender: function () {
        Ext.TabPanel.superclass.afterRender.call(this);
        if (this.autoTabs) {
            this.readTabs(false);
        }
        if (this.activeTab !== undefined) {
            var item = Ext.isObject(this.activeTab) ? this.activeTab : this.items.get(this.activeTab);
            delete this.activeTab;
            this.setActiveTab(item);
        }
    },


    initEvents: function () {
        Ext.TabPanel.superclass.initEvents.call(this);
        this.mon(this.strip, {
            scope: this,
            mousedown: this.onStripMouseDown,
            contextmenu: this.onStripContextMenu
        });
        if (this.enableTabScroll) {
            this.mon(this.strip, 'mousewheel', this.onWheel, this);
        }
    },


    findTargets: function (e) {
        var item = null,
            itemEl = e.getTarget('li:not(.x-tab-edge)', this.strip);

        if (itemEl) {
            item = this.getComponent(itemEl.id.split(this.idDelimiter)[1]);
            if (item.disabled) {
                return {
                    close: null,
                    item: null,
                    el: null
                };
            }
        }
        return {
            close: e.getTarget('.x-tab-strip-close', this.strip),
            item: item,
            el: itemEl
        };
    },


    onStripMouseDown: function (e) {
        if (e.button !== 0) {
            return;
        }
        e.preventDefault();
        var t = this.findTargets(e);
        if (t.close) {
            if (t.item.fireEvent('beforeclose', t.item) !== false) {
                t.item.fireEvent('close', t.item);
                this.remove(t.item);
            }
            return;
        }
        if (t.item && t.item != this.activeTab) {
            this.setActiveTab(t.item);
        }
    },


    onStripContextMenu: function (e) {
        e.preventDefault();
        var t = this.findTargets(e);
        if (t.item) {
            this.fireEvent('contextmenu', this, t.item, e);
        }
    },


    readTabs: function (removeExisting) {
        if (removeExisting === true) {
            this.items.each(function (item) {
                this.remove(item);
            }, this);
        }
        var tabs = this.el.query(this.autoTabSelector);
        for (var i = 0, len = tabs.length; i < len; i++) {
            var tab = tabs[i],
                title = tab.getAttribute('title');
            tab.removeAttribute('title');
            this.add({
                title: title,
                contentEl: tab
            });
        }
    },


    initTab: function (item, index) {
        var before = this.strip.dom.childNodes[index],
            p = this.getTemplateArgs(item),
            el = before ?
                 this.itemTpl.insertBefore(before, p) :
                 this.itemTpl.append(this.strip, p),
            cls = 'x-tab-strip-over',
            tabEl = Ext.get(el);

        tabEl.hover(function () {
            if (!item.disabled) {
                tabEl.addClass(cls);
            }
        }, function () {
            tabEl.removeClass(cls);
        });

        if (item.tabTip) {
            tabEl.child('span.x-tab-strip-text', true).qtip = item.tabTip;
        }
        item.tabEl = el;


        tabEl.select('a').on('click', function (e) {
            if (!e.getPageX()) {
                this.onStripMouseDown(e);
            }
        }, this, { preventDefault: true });

        item.on({
            scope: this,
            disable: this.onItemDisabled,
            enable: this.onItemEnabled,
            titlechange: this.onItemTitleChanged,
            iconchange: this.onItemIconChanged,
            beforeshow: this.onBeforeShowItem
        });
    },




    getTemplateArgs: function (item) {
        var cls = item.closable ? 'x-tab-strip-closable' : '';
        if (item.disabled) {
            cls += ' x-item-disabled';
        }
        if (item.iconCls) {
            cls += ' x-tab-with-icon';
        }
        if (item.tabCls) {
            cls += ' ' + item.tabCls;
        }

        return {
            id: this.id + this.idDelimiter + item.getItemId(),
            text: item.title,
            cls: cls,
            iconCls: item.iconCls || ''
        };
    },


    onAdd: function (c) {
        Ext.TabPanel.superclass.onAdd.call(this, c);
        if (this.rendered) {
            var items = this.items;
            this.initTab(c, items.indexOf(c));
            this.delegateUpdates();
        }
    },


    onBeforeAdd: function (item) {
        var existing = item.events ? (this.items.containsKey(item.getItemId()) ? item : null) : this.items.get(item);
        if (existing) {
            this.setActiveTab(item);
            return false;
        }
        Ext.TabPanel.superclass.onBeforeAdd.apply(this, arguments);
        var es = item.elements;
        item.elements = es ? es.replace(',header', '') : es;
        item.border = (item.border === true);
    },


    onRemove: function (c) {
        var te = Ext.get(c.tabEl);

        if (te) {
            te.select('a').removeAllListeners();
            Ext.destroy(te);
        }
        Ext.TabPanel.superclass.onRemove.call(this, c);
        this.stack.remove(c);
        delete c.tabEl;
        c.un('disable', this.onItemDisabled, this);
        c.un('enable', this.onItemEnabled, this);
        c.un('titlechange', this.onItemTitleChanged, this);
        c.un('iconchange', this.onItemIconChanged, this);
        c.un('beforeshow', this.onBeforeShowItem, this);
        if (c == this.activeTab) {
            var next = this.stack.next();
            if (next) {
                this.setActiveTab(next);
            } else if (this.items.getCount() > 0) {
                this.setActiveTab(0);
            } else {
                this.setActiveTab(null);
            }
        }
        if (!this.destroying) {
            this.delegateUpdates();
        }
    },


    onBeforeShowItem: function (item) {
        if (item != this.activeTab) {
            this.setActiveTab(item);
            return false;
        }
    },


    onItemDisabled: function (item) {
        var el = this.getTabEl(item);
        if (el) {
            Ext.fly(el).addClass('x-item-disabled');
        }
        this.stack.remove(item);
    },


    onItemEnabled: function (item) {
        var el = this.getTabEl(item);
        if (el) {
            Ext.fly(el).removeClass('x-item-disabled');
        }
    },


    onItemTitleChanged: function (item) {
        var el = this.getTabEl(item);
        if (el) {
            Ext.fly(el).child('span.x-tab-strip-text', true).innerHTML = item.title;
        }
    },


    onItemIconChanged: function (item, iconCls, oldCls) {
        var el = this.getTabEl(item);
        if (el) {
            el = Ext.get(el);
            el.child('span.x-tab-strip-text').replaceClass(oldCls, iconCls);
            el[Ext.isEmpty(iconCls) ? 'removeClass' : 'addClass']('x-tab-with-icon');
        }
    },


    getTabEl: function (item) {
        var c = this.getComponent(item);
        return c ? c.tabEl : null;
    },


    onResize: function () {
        Ext.TabPanel.superclass.onResize.apply(this, arguments);
        this.delegateUpdates();
    },


    beginUpdate: function () {
        this.suspendUpdates = true;
    },


    endUpdate: function () {
        this.suspendUpdates = false;
        this.delegateUpdates();
    },


    hideTabStripItem: function (item) {
        item = this.getComponent(item);
        var el = this.getTabEl(item);
        if (el) {
            el.style.display = 'none';
            this.delegateUpdates();
        }
        this.stack.remove(item);
    },


    unhideTabStripItem: function (item) {
        item = this.getComponent(item);
        var el = this.getTabEl(item);
        if (el) {
            el.style.display = '';
            this.delegateUpdates();
        }
    },


    delegateUpdates: function () {
        var rendered = this.rendered;
        if (this.suspendUpdates) {
            return;
        }
        if (this.resizeTabs && rendered) {
            this.autoSizeTabs();
        }
        if (this.enableTabScroll && rendered) {
            this.autoScrollTabs();
        }
    },


    autoSizeTabs: function () {
        var count = this.items.length,
            ce = this.tabPosition != 'bottom' ? 'header' : 'footer',
            ow = this[ce].dom.offsetWidth,
            aw = this[ce].dom.clientWidth;

        if (!this.resizeTabs || count < 1 || !aw) {
            return;
        }

        var each = Math.max(Math.min(Math.floor((aw - 4) / count) - this.tabMargin, this.tabWidth), this.minTabWidth);
        this.lastTabWidth = each;
        var lis = this.strip.query('li:not(.x-tab-edge)');
        for (var i = 0, len = lis.length; i < len; i++) {
            var li = lis[i],
                inner = Ext.fly(li).child('.x-tab-strip-inner', true),
                tw = li.offsetWidth,
                iw = inner.offsetWidth;
            inner.style.width = (each - (tw - iw)) + 'px';
        }
    },


    adjustBodyWidth: function (w) {
        if (this.header) {
            this.header.setWidth(w);
        }
        if (this.footer) {
            this.footer.setWidth(w);
        }
        return w;
    },


    setActiveTab: function (item) {
        item = this.getComponent(item);
        if (this.fireEvent('beforetabchange', this, item, this.activeTab) === false) {
            return;
        }
        if (!this.rendered) {
            this.activeTab = item;
            return;
        }
        if (this.activeTab != item) {
            if (this.activeTab) {
                var oldEl = this.getTabEl(this.activeTab);
                if (oldEl) {
                    Ext.fly(oldEl).removeClass('x-tab-strip-active');
                }
            }
            this.activeTab = item;
            if (item) {
                var el = this.getTabEl(item);
                Ext.fly(el).addClass('x-tab-strip-active');
                this.stack.add(item);

                this.layout.setActiveItem(item);

                this.delegateUpdates();
                if (this.scrolling) {
                    this.scrollToTab(item, this.animScroll);
                }
            }
            this.fireEvent('tabchange', this, item);
        }
    },


    getActiveTab: function () {
        return this.activeTab || null;
    },


    getItem: function (item) {
        return this.getComponent(item);
    },


    autoScrollTabs: function () {
        this.pos = this.tabPosition == 'bottom' ? this.footer : this.header;
        var count = this.items.length,
            ow = this.pos.dom.offsetWidth,
            tw = this.pos.dom.clientWidth,
            wrap = this.stripWrap,
            wd = wrap.dom,
            cw = wd.offsetWidth,
            pos = this.getScrollPos(),
            l = this.edge.getOffsetsTo(this.stripWrap)[0] + pos;

        if (!this.enableTabScroll || cw < 20) {
            return;
        }
        if (count == 0 || l <= tw) {

            wd.scrollLeft = 0;
            wrap.setWidth(tw);
            if (this.scrolling) {
                this.scrolling = false;
                this.pos.removeClass('x-tab-scrolling');
                this.scrollLeft.hide();
                this.scrollRight.hide();

                if (Ext.isAir || Ext.isWebKit) {
                    wd.style.marginLeft = '';
                    wd.style.marginRight = '';
                }
            }
        } else {
            if (!this.scrolling) {
                this.pos.addClass('x-tab-scrolling');

                if (Ext.isAir || Ext.isWebKit) {
                    wd.style.marginLeft = '18px';
                    wd.style.marginRight = '18px';
                }
            }
            tw -= wrap.getMargins('lr');
            wrap.setWidth(tw > 20 ? tw : 20);
            if (!this.scrolling) {
                if (!this.scrollLeft) {
                    this.createScrollers();
                } else {
                    this.scrollLeft.show();
                    this.scrollRight.show();
                }
            }
            this.scrolling = true;
            if (pos > (l - tw)) {
                wd.scrollLeft = l - tw;
            } else {
                this.scrollToTab(this.activeTab, false);
            }
            this.updateScrollButtons();
        }
    },


    createScrollers: function () {
        this.pos.addClass('x-tab-scrolling-' + this.tabPosition);
        var h = this.stripWrap.dom.offsetHeight;


        var sl = this.pos.insertFirst({
            cls: 'x-tab-scroller-left'
        });
        sl.setHeight(h);
        sl.addClassOnOver('x-tab-scroller-left-over');
        this.leftRepeater = new Ext.util.ClickRepeater(sl, {
            interval: this.scrollRepeatInterval,
            handler: this.onScrollLeft,
            scope: this
        });
        this.scrollLeft = sl;


        var sr = this.pos.insertFirst({
            cls: 'x-tab-scroller-right'
        });
        sr.setHeight(h);
        sr.addClassOnOver('x-tab-scroller-right-over');
        this.rightRepeater = new Ext.util.ClickRepeater(sr, {
            interval: this.scrollRepeatInterval,
            handler: this.onScrollRight,
            scope: this
        });
        this.scrollRight = sr;
    },


    getScrollWidth: function () {
        return this.edge.getOffsetsTo(this.stripWrap)[0] + this.getScrollPos();
    },


    getScrollPos: function () {
        return parseInt(this.stripWrap.dom.scrollLeft, 10) || 0;
    },


    getScrollArea: function () {
        return parseInt(this.stripWrap.dom.clientWidth, 10) || 0;
    },


    getScrollAnim: function () {
        return { duration: this.scrollDuration, callback: this.updateScrollButtons, scope: this };
    },


    getScrollIncrement: function () {
        return this.scrollIncrement || (this.resizeTabs ? this.lastTabWidth + 2 : 100);
    },



    scrollToTab: function (item, animate) {
        if (!item) {
            return;
        }
        var el = this.getTabEl(item),
            pos = this.getScrollPos(),
            area = this.getScrollArea(),
            left = Ext.fly(el).getOffsetsTo(this.stripWrap)[0] + pos,
            right = left + el.offsetWidth;
        if (left < pos) {
            this.scrollTo(left, animate);
        } else if (right > (pos + area)) {
            this.scrollTo(right - area, animate);
        }
    },


    scrollTo: function (pos, animate) {
        this.stripWrap.scrollTo('left', pos, animate ? this.getScrollAnim() : false);
        if (!animate) {
            this.updateScrollButtons();
        }
    },

    onWheel: function (e) {
        var d = e.getWheelDelta() * this.wheelIncrement * -1;
        e.stopEvent();

        var pos = this.getScrollPos(),
            newpos = pos + d,
            sw = this.getScrollWidth() - this.getScrollArea();

        var s = Math.max(0, Math.min(sw, newpos));
        if (s != pos) {
            this.scrollTo(s, false);
        }
    },


    onScrollRight: function () {
        var sw = this.getScrollWidth() - this.getScrollArea(),
            pos = this.getScrollPos(),
            s = Math.min(sw, pos + this.getScrollIncrement());
        if (s != pos) {
            this.scrollTo(s, this.animScroll);
        }
    },


    onScrollLeft: function () {
        var pos = this.getScrollPos(),
            s = Math.max(0, pos - this.getScrollIncrement());
        if (s != pos) {
            this.scrollTo(s, this.animScroll);
        }
    },


    updateScrollButtons: function () {
        var pos = this.getScrollPos();
        this.scrollLeft[pos === 0 ? 'addClass' : 'removeClass']('x-tab-scroller-left-disabled');
        this.scrollRight[pos >= (this.getScrollWidth() - this.getScrollArea()) ? 'addClass' : 'removeClass']('x-tab-scroller-right-disabled');
    },


    beforeDestroy: function () {
        Ext.destroy(this.leftRepeater, this.rightRepeater);
        this.deleteMembers('strip', 'edge', 'scrollLeft', 'scrollRight', 'stripWrap');
        this.activeTab = null;
        Ext.TabPanel.superclass.beforeDestroy.apply(this);
    }













});
Ext.reg('tabpanel', Ext.TabPanel);


Ext.TabPanel.prototype.activate = Ext.TabPanel.prototype.setActiveTab;


Ext.TabPanel.AccessStack = function () {
    var items = [];
    return {
        add: function (item) {
            items.push(item);
            if (items.length > 10) {
                items.shift();
            }
        },

        remove: function (item) {
            var s = [];
            for (var i = 0, len = items.length; i < len; i++) {
                if (items[i] != item) {
                    s.push(items[i]);
                }
            }
            items = s;
        },

        next: function () {
            return items.pop();
        }
    };
};

Ext.Button = Ext.extend(Ext.BoxComponent, {

    hidden: false,

    disabled: false,

    pressed: false,






    enableToggle: false,



    menuAlign: 'tl-bl?',




    type: 'button',


    menuClassTarget: 'tr:nth(2)',


    clickEvent: 'click',


    handleMouseEvents: true,


    tooltipType: 'qtip',


    buttonSelector: 'button:first-child',


    scale: 'small',




    iconAlign: 'left',


    arrowAlign: 'right',






    initComponent: function () {
        Ext.Button.superclass.initComponent.call(this);

        this.addEvents(

            'click',

            'toggle',

            'mouseover',

            'mouseout',

            'menushow',

            'menuhide',

            'menutriggerover',

            'menutriggerout'
        );
        if (this.menu) {
            this.menu = Ext.menu.MenuMgr.get(this.menu);
        }
        if (Ext.isString(this.toggleGroup)) {
            this.enableToggle = true;
        }
    },


    getTemplateArgs: function () {
        return [this.type, 'x-btn-' + this.scale + ' x-btn-icon-' + this.scale + '-' + this.iconAlign, this.getMenuClass(), this.cls, this.id];
    },


    setButtonClass: function () {
        if (this.useSetClass) {
            if (!Ext.isEmpty(this.oldCls)) {
                this.el.removeClass([this.oldCls, 'x-btn-pressed']);
            }
            this.oldCls = (this.iconCls || this.icon) ? (this.text ? 'x-btn-text-icon' : 'x-btn-icon') : 'x-btn-noicon';
            this.el.addClass([this.oldCls, this.pressed ? 'x-btn-pressed' : null]);
        }
    },


    getMenuClass: function () {
        return this.menu ? (this.arrowAlign != 'bottom' ? 'x-btn-arrow' : 'x-btn-arrow-bottom') : '';
    },


    onRender: function (ct, position) {
        if (!this.template) {
            if (!Ext.Button.buttonTemplate) {

                Ext.Button.buttonTemplate = new Ext.Template(
                    '<table id="{4}" cellspacing="0" class="x-btn {3}"><tbody class="{1}">',
                    '<tr><td class="x-btn-tl"><i>&#160;</i></td><td class="x-btn-tc"></td><td class="x-btn-tr"><i>&#160;</i></td></tr>',
                    '<tr><td class="x-btn-ml"><i>&#160;</i></td><td class="x-btn-mc"><em class="{2}" unselectable="on"><button type="{0}"></button></em></td><td class="x-btn-mr"><i>&#160;</i></td></tr>',
                    '<tr><td class="x-btn-bl"><i>&#160;</i></td><td class="x-btn-bc"></td><td class="x-btn-br"><i>&#160;</i></td></tr>',
                    '</tbody></table>');
                Ext.Button.buttonTemplate.compile();
            }
            this.template = Ext.Button.buttonTemplate;
        }

        var btn, targs = this.getTemplateArgs();

        if (position) {
            btn = this.template.insertBefore(position, targs, true);
        } else {
            btn = this.template.append(ct, targs, true);
        }

        this.btnEl = btn.child(this.buttonSelector);
        this.mon(this.btnEl, {
            scope: this,
            focus: this.onFocus,
            blur: this.onBlur
        });

        this.initButtonEl(btn, this.btnEl);

        Ext.ButtonToggleMgr.register(this);
    },


    initButtonEl: function (btn, btnEl) {
        this.el = btn;
        this.setIcon(this.icon);
        this.setText(this.text);
        this.setIconClass(this.iconCls);
        if (Ext.isDefined(this.tabIndex)) {
            btnEl.dom.tabIndex = this.tabIndex;
        }
        if (this.tooltip) {
            this.setTooltip(this.tooltip, true);
        }

        if (this.handleMouseEvents) {
            this.mon(btn, {
                scope: this,
                mouseover: this.onMouseOver,
                mousedown: this.onMouseDown
            });



        }

        if (this.menu) {
            this.mon(this.menu, {
                scope: this,
                show: this.onMenuShow,
                hide: this.onMenuHide
            });
        }

        if (this.repeat) {
            var repeater = new Ext.util.ClickRepeater(btn, Ext.isObject(this.repeat) ? this.repeat : {});
            this.mon(repeater, 'click', this.onRepeatClick, this);
        } else {
            this.mon(btn, this.clickEvent, this.onClick, this);
        }
    },


    afterRender: function () {
        Ext.Button.superclass.afterRender.call(this);
        this.useSetClass = true;
        this.setButtonClass();
        this.doc = Ext.getDoc();
        this.doAutoWidth();
    },


    setIconClass: function (cls) {
        this.iconCls = cls;
        if (this.el) {
            this.btnEl.dom.className = '';
            this.btnEl.addClass(['x-btn-text', cls || '']);
            this.setButtonClass();
        }
        return this;
    },


    setTooltip: function (tooltip, initial) {
        if (this.rendered) {
            if (!initial) {
                this.clearTip();
            }
            if (Ext.isObject(tooltip)) {
                Ext.QuickTips.register(Ext.apply({
                    target: this.btnEl.id
                }, tooltip));
                this.tooltip = tooltip;
            } else {
                this.btnEl.dom[this.tooltipType] = tooltip;
            }
        } else {
            this.tooltip = tooltip;
        }
        return this;
    },


    clearTip: function () {
        if (Ext.isObject(this.tooltip)) {
            Ext.QuickTips.unregister(this.btnEl);
        }
    },


    beforeDestroy: function () {
        if (this.rendered) {
            this.clearTip();
        }
        if (this.menu && this.destroyMenu !== false) {
            Ext.destroy(this.btnEl, this.menu);
        }
        Ext.destroy(this.repeater);
    },


    onDestroy: function () {
        if (this.rendered) {
            this.doc.un('mouseover', this.monitorMouseOver, this);
            this.doc.un('mouseup', this.onMouseUp, this);
            delete this.doc;
            delete this.btnEl;
            Ext.ButtonToggleMgr.unregister(this);
        }
        Ext.Button.superclass.onDestroy.call(this);
    },


    doAutoWidth: function () {
        if (this.autoWidth !== false && this.el && this.text && this.width === undefined) {
            this.el.setWidth('auto');
            if (Ext.isIE7 && Ext.isStrict) {
                var ib = this.btnEl;
                if (ib && ib.getWidth() > 20) {
                    ib.clip();
                    ib.setWidth(Ext.util.TextMetrics.measure(ib, this.text).width + ib.getFrameWidth('lr'));
                }
            }
            if (this.minWidth) {
                if (this.el.getWidth() < this.minWidth) {
                    this.el.setWidth(this.minWidth);
                }
            }
        }
    },


    setHandler: function (handler, scope) {
        this.handler = handler;
        this.scope = scope;
        return this;
    },


    setText: function (text) {
        this.text = text;
        if (this.el) {
            this.btnEl.update(text || '&#160;');
            this.setButtonClass();
        }
        this.doAutoWidth();
        return this;
    },


    setIcon: function (icon) {
        this.icon = icon;
        if (this.el) {
            this.btnEl.setStyle('background-image', icon ? 'url(' + icon + ')' : '');
            this.setButtonClass();
        }
        return this;
    },


    getText: function () {
        return this.text;
    },


    toggle: function (state, suppressEvent) {
        state = state === undefined ? !this.pressed : !!state;
        if (state != this.pressed) {
            if (this.rendered) {
                this.el[state ? 'addClass' : 'removeClass']('x-btn-pressed');
            }
            this.pressed = state;
            if (!suppressEvent) {
                this.fireEvent('toggle', this, state);
                if (this.toggleHandler) {
                    this.toggleHandler.call(this.scope || this, this, state);
                }
            }
        }
        return this;
    },


    onDisable: function () {
        this.onDisableChange(true);
    },


    onEnable: function () {
        this.onDisableChange(false);
    },

    onDisableChange: function (disabled) {
        if (this.el) {
            if (!Ext.isIE6 || !this.text) {
                this.el[disabled ? 'addClass' : 'removeClass'](this.disabledClass);
            }
            this.el.dom.disabled = disabled;
        }
        this.disabled = disabled;
    },


    showMenu: function () {
        if (this.rendered && this.menu) {
            if (this.tooltip) {
                Ext.QuickTips.getQuickTip().cancelShow(this.btnEl);
            }
            if (this.menu.isVisible()) {
                this.menu.hide();
            }
            this.menu.ownerCt = this;
            this.menu.show(this.el, this.menuAlign);
        }
        return this;
    },


    hideMenu: function () {
        if (this.hasVisibleMenu()) {
            this.menu.hide();
        }
        return this;
    },


    hasVisibleMenu: function () {
        return this.menu && this.menu.ownerCt == this && this.menu.isVisible();
    },


    onRepeatClick: function (repeat, e) {
        this.onClick(e);
    },


    onClick: function (e) {
        if (e) {
            e.preventDefault();
        }
        if (e.button !== 0) {
            return;
        }
        if (!this.disabled) {
            this.doToggle();
            if (this.menu && !this.hasVisibleMenu() && !this.ignoreNextClick) {
                this.showMenu();
            }
            this.fireEvent('click', this, e);
            if (this.handler) {

                this.handler.call(this.scope || this, this, e);
            }
        }
    },


    doToggle: function () {
        if (this.enableToggle && (this.allowDepress !== false || !this.pressed)) {
            this.toggle();
        }
    },


    isMenuTriggerOver: function (e, internal) {
        return this.menu && !internal;
    },


    isMenuTriggerOut: function (e, internal) {
        return this.menu && !internal;
    },


    onMouseOver: function (e) {
        if (!this.disabled) {
            var internal = e.within(this.el, true);
            if (!internal) {
                this.el.addClass('x-btn-over');
                if (!this.monitoringMouseOver) {
                    this.doc.on('mouseover', this.monitorMouseOver, this);
                    this.monitoringMouseOver = true;
                }
                this.fireEvent('mouseover', this, e);
            }
            if (this.isMenuTriggerOver(e, internal)) {
                this.fireEvent('menutriggerover', this, this.menu, e);
            }
        }
    },


    monitorMouseOver: function (e) {
        if (e.target != this.el.dom && !e.within(this.el)) {
            if (this.monitoringMouseOver) {
                this.doc.un('mouseover', this.monitorMouseOver, this);
                this.monitoringMouseOver = false;
            }
            this.onMouseOut(e);
        }
    },


    onMouseOut: function (e) {
        var internal = e.within(this.el) && e.target != this.el.dom;
        this.el.removeClass('x-btn-over');
        this.fireEvent('mouseout', this, e);
        if (this.isMenuTriggerOut(e, internal)) {
            this.fireEvent('menutriggerout', this, this.menu, e);
        }
    },

    focus: function () {
        this.btnEl.focus();
    },

    blur: function () {
        this.btnEl.blur();
    },


    onFocus: function (e) {
        if (!this.disabled) {
            this.el.addClass('x-btn-focus');
        }
    },

    onBlur: function (e) {
        this.el.removeClass('x-btn-focus');
    },


    getClickEl: function (e, isUp) {
        return this.el;
    },


    onMouseDown: function (e) {
        if (!this.disabled && e.button === 0) {
            this.getClickEl(e).addClass('x-btn-click');
            this.doc.on('mouseup', this.onMouseUp, this);
        }
    },

    onMouseUp: function (e) {
        if (e.button === 0) {
            this.getClickEl(e, true).removeClass('x-btn-click');
            this.doc.un('mouseup', this.onMouseUp, this);
        }
    },

    onMenuShow: function (e) {
        if (this.menu.ownerCt == this) {
            this.menu.ownerCt = this;
            this.ignoreNextClick = 0;
            this.el.addClass('x-btn-menu-active');
            this.fireEvent('menushow', this, this.menu);
        }
    },

    onMenuHide: function (e) {
        if (this.menu.ownerCt == this) {
            this.el.removeClass('x-btn-menu-active');
            this.ignoreNextClick = this.restoreClick.defer(250, this);
            this.fireEvent('menuhide', this, this.menu);
            delete this.menu.ownerCt;
        }
    },


    restoreClick: function () {
        this.ignoreNextClick = 0;
    }







});
Ext.reg('button', Ext.Button);


Ext.ButtonToggleMgr = function () {
    var groups = {};

    function toggleGroup(btn, state) {
        if (state) {
            var g = groups[btn.toggleGroup];
            for (var i = 0, l = g.length; i < l; i++) {
                if (g[i] != btn) {
                    g[i].toggle(false);
                }
            }
        }
    }

    return {
        register: function (btn) {
            if (!btn.toggleGroup) {
                return;
            }
            var g = groups[btn.toggleGroup];
            if (!g) {
                g = groups[btn.toggleGroup] = [];
            }
            g.push(btn);
            btn.on('toggle', toggleGroup);
        },

        unregister: function (btn) {
            if (!btn.toggleGroup) {
                return;
            }
            var g = groups[btn.toggleGroup];
            if (g) {
                g.remove(btn);
                btn.un('toggle', toggleGroup);
            }
        },


        getPressed: function (group) {
            var g = groups[group];
            if (g) {
                for (var i = 0, len = g.length; i < len; i++) {
                    if (g[i].pressed === true) {
                        return g[i];
                    }
                }
            }
            return null;
        }
    };
} ();

Ext.SplitButton = Ext.extend(Ext.Button, {

    arrowSelector: 'em',
    split: true,


    initComponent: function () {
        Ext.SplitButton.superclass.initComponent.call(this);

        this.addEvents("arrowclick");
    },


    onRender: function () {
        Ext.SplitButton.superclass.onRender.apply(this, arguments);
        if (this.arrowTooltip) {
            this.el.child(this.arrowSelector).dom[this.tooltipType] = this.arrowTooltip;
        }
    },


    setArrowHandler: function (handler, scope) {
        this.arrowHandler = handler;
        this.scope = scope;
    },

    getMenuClass: function () {
        return 'x-btn-split' + (this.arrowAlign == 'bottom' ? '-bottom' : '');
    },

    isClickOnArrow: function (e) {
        if (this.arrowAlign != 'bottom') {
            var visBtn = this.el.child('em.x-btn-split');
            var right = visBtn.getRegion().right - visBtn.getPadding('r');
            return e.getPageX() > right;
        } else {
            return e.getPageY() > this.btnEl.getRegion().bottom;
        }
    },


    onClick: function (e, t) {
        e.preventDefault();
        if (!this.disabled) {
            if (this.isClickOnArrow(e)) {
                if (this.menu && !this.menu.isVisible() && !this.ignoreNextClick) {
                    this.showMenu();
                }
                this.fireEvent("arrowclick", this, e);
                if (this.arrowHandler) {
                    this.arrowHandler.call(this.scope || this, this, e);
                }
            } else {
                this.doToggle();
                this.fireEvent("click", this, e);
                if (this.handler) {
                    this.handler.call(this.scope || this, this, e);
                }
            }
        }
    },


    isMenuTriggerOver: function (e) {
        return this.menu && e.target.tagName == this.arrowSelector;
    },


    isMenuTriggerOut: function (e, internal) {
        return this.menu && e.target.tagName != this.arrowSelector;
    }
});

Ext.reg('splitbutton', Ext.SplitButton);
Ext.CycleButton = Ext.extend(Ext.SplitButton, {








    getItemText: function (item) {
        if (item && this.showText === true) {
            var text = '';
            if (this.prependText) {
                text += this.prependText;
            }
            text += item.text;
            return text;
        }
        return undefined;
    },


    setActiveItem: function (item, suppressEvent) {
        if (!Ext.isObject(item)) {
            item = this.menu.getComponent(item);
        }
        if (item) {
            if (!this.rendered) {
                this.text = this.getItemText(item);
                this.iconCls = item.iconCls;
            } else {
                var t = this.getItemText(item);
                if (t) {
                    this.setText(t);
                }
                this.setIconClass(item.iconCls);
            }
            this.activeItem = item;
            if (!item.checked) {
                item.setChecked(true, false);
            }
            if (this.forceIcon) {
                this.setIconClass(this.forceIcon);
            }
            if (!suppressEvent) {
                this.fireEvent('change', this, item);
            }
        }
    },


    getActiveItem: function () {
        return this.activeItem;
    },


    initComponent: function () {
        this.addEvents(

            "change"
        );

        if (this.changeHandler) {
            this.on('change', this.changeHandler, this.scope || this);
            delete this.changeHandler;
        }

        this.itemCount = this.items.length;

        this.menu = { cls: 'x-cycle-menu', items: [] };
        var checked = 0;
        Ext.each(this.items, function (item, i) {
            Ext.apply(item, {
                group: item.group || this.id,
                itemIndex: i,
                checkHandler: this.checkHandler,
                scope: this,
                checked: item.checked || false
            });
            this.menu.items.push(item);
            if (item.checked) {
                checked = i;
            }
        }, this);
        Ext.CycleButton.superclass.initComponent.call(this);
        this.on('click', this.toggleSelected, this);
        this.setActiveItem(checked, true);
    },


    checkHandler: function (item, pressed) {
        if (pressed) {
            this.setActiveItem(item);
        }
    },


    toggleSelected: function () {
        var m = this.menu;
        m.render();

        if (!m.hasLayout) {
            m.doLayout();
        }

        var nextIdx, checkItem;
        for (var i = 1; i < this.itemCount; i++) {
            nextIdx = (this.activeItem.itemIndex + i) % this.itemCount;

            checkItem = m.items.itemAt(nextIdx);

            if (!checkItem.disabled) {
                checkItem.setChecked(true);
                break;
            }
        }
    }
});
Ext.reg('cycle', Ext.CycleButton);
Ext.Toolbar = function (config) {
    if (Ext.isArray(config)) {
        config = { items: config, layout: 'toolbar' };
    } else {
        config = Ext.apply({
            layout: 'toolbar'
        }, config);
        if (config.buttons) {
            config.items = config.buttons;
        }
    }
    Ext.Toolbar.superclass.constructor.call(this, config);
};

(function () {

    var T = Ext.Toolbar;

    Ext.extend(T, Ext.Container, {

        defaultType: 'button',



        enableOverflow: false,




        trackMenus: true,
        internalDefaults: { removeMode: 'container', hideParent: true },
        toolbarCls: 'x-toolbar',

        initComponent: function () {
            T.superclass.initComponent.call(this);


            this.addEvents('overflowchange');
        },


        onRender: function (ct, position) {
            if (!this.el) {
                if (!this.autoCreate) {
                    this.autoCreate = {
                        cls: this.toolbarCls + ' x-small-editor'
                    };
                }
                this.el = ct.createChild(Ext.apply({ id: this.id }, this.autoCreate), position);
                Ext.Toolbar.superclass.onRender.apply(this, arguments);
            }
        },




        lookupComponent: function (c) {
            if (Ext.isString(c)) {
                if (c == '-') {
                    c = new T.Separator();
                } else if (c == ' ') {
                    c = new T.Spacer();
                } else if (c == '->') {
                    c = new T.Fill();
                } else {
                    c = new T.TextItem(c);
                }
                this.applyDefaults(c);
            } else {
                if (c.isFormField || c.render) {
                    c = this.createComponent(c);
                } else if (c.tag) {
                    c = new T.Item({ autoEl: c });
                } else if (c.tagName) {
                    c = new T.Item({ el: c });
                } else if (Ext.isObject(c)) {
                    c = c.xtype ? this.createComponent(c) : this.constructButton(c);
                }
            }
            return c;
        },


        applyDefaults: function (c) {
            if (!Ext.isString(c)) {
                c = Ext.Toolbar.superclass.applyDefaults.call(this, c);
                var d = this.internalDefaults;
                if (c.events) {
                    Ext.applyIf(c.initialConfig, d);
                    Ext.apply(c, d);
                } else {
                    Ext.applyIf(c, d);
                }
            }
            return c;
        },


        addSeparator: function () {
            return this.add(new T.Separator());
        },


        addSpacer: function () {
            return this.add(new T.Spacer());
        },


        addFill: function () {
            this.add(new T.Fill());
        },


        addElement: function (el) {
            return this.addItem(new T.Item({ el: el }));
        },


        addItem: function (item) {
            return this.add.apply(this, arguments);
        },


        addButton: function (config) {
            if (Ext.isArray(config)) {
                var buttons = [];
                for (var i = 0, len = config.length; i < len; i++) {
                    buttons.push(this.addButton(config[i]));
                }
                return buttons;
            }
            return this.add(this.constructButton(config));
        },


        addText: function (text) {
            return this.addItem(new T.TextItem(text));
        },


        addDom: function (config) {
            return this.add(new T.Item({ autoEl: config }));
        },


        addField: function (field) {
            return this.add(field);
        },


        insertButton: function (index, item) {
            if (Ext.isArray(item)) {
                var buttons = [];
                for (var i = 0, len = item.length; i < len; i++) {
                    buttons.push(this.insertButton(index + i, item[i]));
                }
                return buttons;
            }
            return Ext.Toolbar.superclass.insert.call(this, index, item);
        },


        trackMenu: function (item, remove) {
            if (this.trackMenus && item.menu) {
                var method = remove ? 'mun' : 'mon';
                this[method](item, 'menutriggerover', this.onButtonTriggerOver, this);
                this[method](item, 'menushow', this.onButtonMenuShow, this);
                this[method](item, 'menuhide', this.onButtonMenuHide, this);
            }
        },


        constructButton: function (item) {
            var b = item.events ? item : this.createComponent(item, item.split ? 'splitbutton' : this.defaultType);
            return b;
        },


        onAdd: function (c) {
            Ext.Toolbar.superclass.onAdd.call(this);
            this.trackMenu(c);
            if (this.disabled) {
                c.disable();
            }
        },


        onRemove: function (c) {
            Ext.Toolbar.superclass.onRemove.call(this);
            if (c == this.activeMenuBtn) {
                delete this.activeMenuBtn;
            }
            this.trackMenu(c, true);
        },


        onDisable: function () {
            this.items.each(function (item) {
                if (item.disable) {
                    item.disable();
                }
            });
        },


        onEnable: function () {
            this.items.each(function (item) {
                if (item.enable) {
                    item.enable();
                }
            });
        },


        onButtonTriggerOver: function (btn) {
            if (this.activeMenuBtn && this.activeMenuBtn != btn) {
                this.activeMenuBtn.hideMenu();
                btn.showMenu();
                this.activeMenuBtn = btn;
            }
        },


        onButtonMenuShow: function (btn) {
            this.activeMenuBtn = btn;
        },


        onButtonMenuHide: function (btn) {
            delete this.activeMenuBtn;
        }
    });
    Ext.reg('toolbar', Ext.Toolbar);


    T.Item = Ext.extend(Ext.BoxComponent, {
        hideParent: true,
        enable: Ext.emptyFn,
        disable: Ext.emptyFn,
        focus: Ext.emptyFn

    });
    Ext.reg('tbitem', T.Item);


    T.Separator = Ext.extend(T.Item, {
        onRender: function (ct, position) {
            this.el = ct.createChild({ tag: 'span', cls: 'xtb-sep' }, position);
        }
    });
    Ext.reg('tbseparator', T.Separator);


    T.Spacer = Ext.extend(T.Item, {


        onRender: function (ct, position) {
            this.el = ct.createChild({ tag: 'div', cls: 'xtb-spacer', style: this.width ? 'width:' + this.width + 'px' : '' }, position);
        }
    });
    Ext.reg('tbspacer', T.Spacer);


    T.Fill = Ext.extend(T.Item, {

        render: Ext.emptyFn,
        isFill: true
    });
    Ext.reg('tbfill', T.Fill);


    T.TextItem = Ext.extend(T.Item, {


        constructor: function (config) {
            T.TextItem.superclass.constructor.call(this, Ext.isString(config) ? { text: config} : config);
        },


        onRender: function (ct, position) {
            this.autoEl = { cls: 'xtb-text', html: this.text || '' };
            T.TextItem.superclass.onRender.call(this, ct, position);
        },


        setText: function (t) {
            if (this.rendered) {
                this.el.update(t);
            } else {
                this.text = t;
            }
        }
    });
    Ext.reg('tbtext', T.TextItem);


    T.Button = Ext.extend(Ext.Button, {});
    T.SplitButton = Ext.extend(Ext.SplitButton, {});
    Ext.reg('tbbutton', T.Button);
    Ext.reg('tbsplit', T.SplitButton);

})();

Ext.ButtonGroup = Ext.extend(Ext.Panel, {


    baseCls: 'x-btn-group',

    layout: 'table',
    defaultType: 'button',

    frame: true,
    internalDefaults: { removeMode: 'container', hideParent: true },

    initComponent: function () {
        this.layoutConfig = this.layoutConfig || {};
        Ext.applyIf(this.layoutConfig, {
            columns: this.columns
        });
        if (!this.title) {
            this.addClass('x-btn-group-notitle');
        }
        this.on('afterlayout', this.onAfterLayout, this);
        Ext.ButtonGroup.superclass.initComponent.call(this);
    },

    applyDefaults: function (c) {
        c = Ext.ButtonGroup.superclass.applyDefaults.call(this, c);
        var d = this.internalDefaults;
        if (c.events) {
            Ext.applyIf(c.initialConfig, d);
            Ext.apply(c, d);
        } else {
            Ext.applyIf(c, d);
        }
        return c;
    },

    onAfterLayout: function () {
        var bodyWidth = this.body.getFrameWidth('lr') + this.body.dom.firstChild.offsetWidth;
        this.body.setWidth(bodyWidth);
        this.el.setWidth(bodyWidth + this.getFrameWidth());
    }

});

Ext.reg('buttongroup', Ext.ButtonGroup);

(function () {

    var T = Ext.Toolbar;

    Ext.PagingToolbar = Ext.extend(Ext.Toolbar, {



        pageSize: 20,


        displayMsg: 'Displaying {0} - {1} of {2}',

        emptyMsg: 'No data to display',

        beforePageText: 'Page',

        afterPageText: 'of {0}',

        firstText: 'First Page',

        prevText: 'Previous Page',

        nextText: 'Next Page',

        lastText: 'Last Page',

        refreshText: 'Refresh',







        initComponent: function () {
            var pagingItems = [this.first = new T.Button({
                tooltip: this.firstText,
                overflowText: this.firstText,
                iconCls: 'x-tbar-page-first',
                disabled: true,
                handler: this.moveFirst,
                scope: this
            }), this.prev = new T.Button({
                tooltip: this.prevText,
                overflowText: this.prevText,
                iconCls: 'x-tbar-page-prev',
                disabled: true,
                handler: this.movePrevious,
                scope: this
            }), '-', this.beforePageText,
        this.inputItem = new Ext.form.NumberField({
            cls: 'x-tbar-page-number',
            allowDecimals: false,
            allowNegative: false,
            enableKeyEvents: true,
            selectOnFocus: true,
            submitValue: false,
            listeners: {
                scope: this,
                keydown: this.onPagingKeyDown,
                blur: this.onPagingBlur
            }
        }), this.afterTextItem = new T.TextItem({
            text: String.format(this.afterPageText, 1)
        }), '-', this.next = new T.Button({
            tooltip: this.nextText,
            overflowText: this.nextText,
            iconCls: 'x-tbar-page-next',
            disabled: true,
            handler: this.moveNext,
            scope: this
        }), this.last = new T.Button({
            tooltip: this.lastText,
            overflowText: this.lastText,
            iconCls: 'x-tbar-page-last',
            disabled: true,
            handler: this.moveLast,
            scope: this
        }), '-', this.refresh = new T.Button({
            tooltip: this.refreshText,
            overflowText: this.refreshText,
            iconCls: 'x-tbar-loading',
            handler: this.doRefresh,
            scope: this
        })];


            var userItems = this.items || this.buttons || [];
            if (this.prependButtons) {
                this.items = userItems.concat(pagingItems);
            } else {
                this.items = pagingItems.concat(userItems);
            }
            delete this.buttons;
            if (this.displayInfo) {
                this.items.push('->');
                this.items.push(this.displayItem = new T.TextItem({}));
            }
            Ext.PagingToolbar.superclass.initComponent.call(this);
            this.addEvents(

            'change',

            'beforechange'
        );
            this.on('afterlayout', this.onFirstLayout, this, { single: true });
            this.cursor = 0;
            this.bindStore(this.store, true);
        },


        onFirstLayout: function () {
            if (this.dsLoaded) {
                this.onLoad.apply(this, this.dsLoaded);
            }
        },


        updateInfo: function () {
            if (this.displayItem) {
                var count = this.store.getCount();
                var msg = count == 0 ?
                this.emptyMsg :
                String.format(
                    this.displayMsg,
                    this.cursor + 1, this.cursor + count, this.store.getTotalCount()
                );
                this.displayItem.setText(msg);
            }
        },


        onLoad: function (store, r, o) {
            if (!this.rendered) {
                this.dsLoaded = [store, r, o];
                return;
            }
            var p = this.getParams();
            this.cursor = (o.params && o.params[p.start]) ? o.params[p.start] : 0;
            var d = this.getPageData(), ap = d.activePage, ps = d.pages;

            this.afterTextItem.setText(String.format(this.afterPageText, d.pages));
            this.inputItem.setValue(ap);
            this.first.setDisabled(ap == 1);
            this.prev.setDisabled(ap == 1);
            this.next.setDisabled(ap == ps);
            this.last.setDisabled(ap == ps);
            this.refresh.enable();
            this.updateInfo();
            this.fireEvent('change', this, d);
        },


        getPageData: function () {
            var total = this.store.getTotalCount();
            return {
                total: total,
                activePage: Math.ceil((this.cursor + this.pageSize) / this.pageSize),
                pages: total < this.pageSize ? 1 : Math.ceil(total / this.pageSize)
            };
        },


        changePage: function (page) {
            this.doLoad(((page - 1) * this.pageSize).constrain(0, this.store.getTotalCount()));
        },


        onLoadError: function () {
            if (!this.rendered) {
                return;
            }
            this.refresh.enable();
        },


        readPage: function (d) {
            var v = this.inputItem.getValue(), pageNum;
            if (!v || isNaN(pageNum = parseInt(v, 10))) {
                this.inputItem.setValue(d.activePage);
                return false;
            }
            return pageNum;
        },

        onPagingFocus: function () {
            this.inputItem.select();
        },


        onPagingBlur: function (e) {
            this.inputItem.setValue(this.getPageData().activePage);
        },


        onPagingKeyDown: function (field, e) {
            var k = e.getKey(), d = this.getPageData(), pageNum;
            if (k == e.RETURN) {
                e.stopEvent();
                pageNum = this.readPage(d);
                if (pageNum !== false) {
                    pageNum = Math.min(Math.max(1, pageNum), d.pages) - 1;
                    this.doLoad(pageNum * this.pageSize);
                }
            } else if (k == e.HOME || k == e.END) {
                e.stopEvent();
                pageNum = k == e.HOME ? 1 : d.pages;
                field.setValue(pageNum);
            } else if (k == e.UP || k == e.PAGEUP || k == e.DOWN || k == e.PAGEDOWN) {
                e.stopEvent();
                if ((pageNum = this.readPage(d))) {
                    var increment = e.shiftKey ? 10 : 1;
                    if (k == e.DOWN || k == e.PAGEDOWN) {
                        increment *= -1;
                    }
                    pageNum += increment;
                    if (pageNum >= 1 & pageNum <= d.pages) {
                        field.setValue(pageNum);
                    }
                }
            }
        },


        getParams: function () {

            return this.paramNames || this.store.paramNames;
        },


        beforeLoad: function () {
            if (this.rendered && this.refresh) {
                this.refresh.disable();
            }
        },


        doLoad: function (start) {
            var o = {}, pn = this.getParams();
            o[pn.start] = start;
            o[pn.limit] = this.pageSize;
            if (this.fireEvent('beforechange', this, o) !== false) {
                this.store.load({ params: o });
            }
        },


        moveFirst: function () {
            this.doLoad(0);
        },


        movePrevious: function () {
            this.doLoad(Math.max(0, this.cursor - this.pageSize));
        },


        moveNext: function () {
            this.doLoad(this.cursor + this.pageSize);
        },


        moveLast: function () {
            var total = this.store.getTotalCount(),
            extra = total % this.pageSize;

            this.doLoad(extra ? (total - extra) : total - this.pageSize);
        },


        doRefresh: function () {
            this.doLoad(this.cursor);
        },


        bindStore: function (store, initial) {
            var doLoad;
            if (!initial && this.store) {
                if (store !== this.store && this.store.autoDestroy) {
                    this.store.destroy();
                } else {
                    this.store.un('beforeload', this.beforeLoad, this);
                    this.store.un('load', this.onLoad, this);
                    this.store.un('exception', this.onLoadError, this);
                }
                if (!store) {
                    this.store = null;
                }
            }
            if (store) {
                store = Ext.StoreMgr.lookup(store);
                store.on({
                    scope: this,
                    beforeload: this.beforeLoad,
                    load: this.onLoad,
                    exception: this.onLoadError
                });
                doLoad = true;
            }
            this.store = store;
            if (doLoad) {
                this.onLoad(store, null, {});
            }
        },


        unbind: function (store) {
            this.bindStore(null);
        },


        bind: function (store) {
            this.bindStore(store);
        },


        onDestroy: function () {
            this.bindStore(null);
            Ext.PagingToolbar.superclass.onDestroy.call(this);
        }
    });

})();
Ext.reg('paging', Ext.PagingToolbar);
Ext.History = (function () {
    var iframe, hiddenField;
    var ready = false;
    var currentToken;

    function getHash() {
        var href = location.href, i = href.indexOf("#");
        return i >= 0 ? href.substr(i + 1) : null;
    }

    function doSave() {
        hiddenField.value = currentToken;
    }

    function handleStateChange(token) {
        currentToken = token;
        Ext.History.fireEvent('change', token);
    }

    function updateIFrame(token) {
        var html = ['<html><body><div id="state">', Ext.util.Format.htmlEncode(token), '</div></body></html>'].join('');
        try {
            var doc = iframe.contentWindow.document;
            doc.open();
            doc.write(html);
            doc.close();
            return true;
        } catch (e) {
            return false;
        }
    }

    function checkIFrame() {
        if (!iframe.contentWindow || !iframe.contentWindow.document) {
            setTimeout(checkIFrame, 10);
            return;
        }

        var doc = iframe.contentWindow.document;
        var elem = doc.getElementById("state");
        var token = elem ? elem.innerText : null;

        var hash = getHash();

        setInterval(function () {

            doc = iframe.contentWindow.document;
            elem = doc.getElementById("state");

            var newtoken = elem ? elem.innerText : null;

            var newHash = getHash();

            if (newtoken !== token) {
                token = newtoken;
                handleStateChange(token);
                top.location.hash = token;
                hash = token;
                doSave();
            } else if (newHash !== hash) {
                hash = newHash;
                updateIFrame(newHash);
            }

        }, 50);

        ready = true;

        Ext.History.fireEvent('ready', Ext.History);
    }

    function startUp() {
        currentToken = hiddenField.value ? hiddenField.value : getHash();

        if (Ext.isIE) {
            checkIFrame();
        } else {
            var hash = getHash();
            setInterval(function () {
                var newHash = getHash();
                if (newHash !== hash) {
                    hash = newHash;
                    handleStateChange(hash);
                    doSave();
                }
            }, 50);
            ready = true;
            Ext.History.fireEvent('ready', Ext.History);
        }
    }

    return {

        fieldId: 'x-history-field',

        iframeId: 'x-history-frame',

        events: {},


        init: function (onReady, scope) {
            if (ready) {
                Ext.callback(onReady, scope, [this]);
                return;
            }
            if (!Ext.isReady) {
                Ext.onReady(function () {
                    Ext.History.init(onReady, scope);
                });
                return;
            }
            hiddenField = Ext.getDom(Ext.History.fieldId);
            if (Ext.isIE) {
                iframe = Ext.getDom(Ext.History.iframeId);
            }
            this.addEvents(

                'ready',

                'change'
            );
            if (onReady) {
                this.on('ready', onReady, scope, { single: true });
            }
            startUp();
        },


        add: function (token, preventDup) {
            if (preventDup !== false) {
                if (this.getToken() == token) {
                    return true;
                }
            }
            if (Ext.isIE) {
                return updateIFrame(token);
            } else {
                top.location.hash = token;
                return true;
            }
        },


        back: function () {
            history.go(-1);
        },


        forward: function () {
            history.go(1);
        },


        getToken: function () {
            return ready ? currentToken : getHash();
        }
    };
})();
Ext.apply(Ext.History, new Ext.util.Observable());
Ext.Tip = Ext.extend(Ext.Panel, {



    minWidth: 40,

    maxWidth: 300,

    shadow: "sides",

    defaultAlign: "tl-bl?",
    autoRender: true,
    quickShowInterval: 250,


    frame: true,
    hidden: true,
    baseCls: 'x-tip',
    floating: { shadow: true, shim: true, useDisplay: true, constrain: false },
    autoHeight: true,

    closeAction: 'hide',


    initComponent: function () {
        Ext.Tip.superclass.initComponent.call(this);
        if (this.closable && !this.title) {
            this.elements += ',header';
        }
    },


    afterRender: function () {
        Ext.Tip.superclass.afterRender.call(this);
        if (this.closable) {
            this.addTool({
                id: 'close',
                handler: this[this.closeAction],
                scope: this
            });
        }
    },


    showAt: function (xy) {
        Ext.Tip.superclass.show.call(this);
        if (this.measureWidth !== false && (!this.initialConfig || typeof this.initialConfig.width != 'number')) {
            this.doAutoWidth();
        }
        if (this.constrainPosition) {
            xy = this.el.adjustForConstraints(xy);
        }
        this.setPagePosition(xy[0], xy[1]);
    },


    doAutoWidth: function (adjust) {
        adjust = adjust || 0;
        var bw = this.body.getTextWidth();
        if (this.title) {
            bw = Math.max(bw, this.header.child('span').getTextWidth(this.title));
        }
        bw += this.getFrameWidth() + (this.closable ? 20 : 0) + this.body.getPadding("lr") + adjust;
        this.setWidth(bw.constrain(this.minWidth, this.maxWidth));


        if (Ext.isIE7 && !this.repainted) {
            this.el.repaint();
            this.repainted = true;
        }
    },


    showBy: function (el, pos) {
        if (!this.rendered) {
            this.render(Ext.getBody());
        }
        this.showAt(this.el.getAlignToXY(el, pos || this.defaultAlign));
    },

    initDraggable: function () {
        this.dd = new Ext.Tip.DD(this, typeof this.draggable == 'boolean' ? null : this.draggable);
        this.header.addClass('x-tip-draggable');
    }
});

Ext.reg('tip', Ext.Tip);


Ext.Tip.DD = function (tip, config) {
    Ext.apply(this, config);
    this.tip = tip;
    Ext.Tip.DD.superclass.constructor.call(this, tip.el.id, 'WindowDD-' + tip.id);
    this.setHandleElId(tip.header.id);
    this.scroll = false;
};

Ext.extend(Ext.Tip.DD, Ext.dd.DD, {
    moveOnly: true,
    scroll: false,
    headerOffsets: [100, 25],
    startDrag: function () {
        this.tip.el.disableShadow();
    },
    endDrag: function (e) {
        this.tip.el.enableShadow(true);
    }
});
Ext.ToolTip = Ext.extend(Ext.Tip, {




    showDelay: 500,

    hideDelay: 200,

    dismissDelay: 5000,


    trackMouse: false,

    anchorToTarget: true,

    anchorOffset: 0,



    targetCounter: 0,

    constrainPosition: false,


    initComponent: function () {
        Ext.ToolTip.superclass.initComponent.call(this);
        this.lastActive = new Date();
        this.initTarget(this.target);
        this.origAnchor = this.anchor;
    },


    onRender: function (ct, position) {
        Ext.ToolTip.superclass.onRender.call(this, ct, position);
        this.anchorCls = 'x-tip-anchor-' + this.getAnchorPosition();
        this.anchorEl = this.el.createChild({
            cls: 'x-tip-anchor ' + this.anchorCls
        });
    },


    afterRender: function () {
        Ext.ToolTip.superclass.afterRender.call(this);
        this.anchorEl.setStyle('z-index', this.el.getZIndex() + 1).setVisibilityMode(Ext.Element.DISPLAY);
    },


    initTarget: function (target) {
        var t;
        if ((t = Ext.get(target))) {
            if (this.target) {
                var tg = Ext.get(this.target);
                this.mun(tg, 'mouseover', this.onTargetOver, this);
                this.mun(tg, 'mouseout', this.onTargetOut, this);
                this.mun(tg, 'mousemove', this.onMouseMove, this);
            }
            this.mon(t, {
                mouseover: this.onTargetOver,
                mouseout: this.onTargetOut,
                mousemove: this.onMouseMove,
                scope: this
            });
            this.target = t;
        }
        if (this.anchor) {
            this.anchorTarget = this.target;
        }
    },


    onMouseMove: function (e) {
        var t = this.delegate ? e.getTarget(this.delegate) : this.triggerElement = true;
        if (t) {
            this.targetXY = e.getXY();
            if (t === this.triggerElement) {
                if (!this.hidden && this.trackMouse) {
                    this.setPagePosition(this.getTargetXY());
                }
            } else {
                this.hide();
                this.lastActive = new Date(0);
                this.onTargetOver(e);
            }
        } else if (!this.closable && this.isVisible()) {
            this.hide();
        }
    },


    getTargetXY: function () {
        if (this.delegate) {
            this.anchorTarget = this.triggerElement;
        }
        if (this.anchor) {
            this.targetCounter++;
            var offsets = this.getOffsets(),
                xy = (this.anchorToTarget && !this.trackMouse) ? this.el.getAlignToXY(this.anchorTarget, this.getAnchorAlign()) : this.targetXY,
                dw = Ext.lib.Dom.getViewWidth() - 5,
                dh = Ext.lib.Dom.getViewHeight() - 5,
                de = document.documentElement,
                bd = document.body,
                scrollX = (de.scrollLeft || bd.scrollLeft || 0) + 5,
                scrollY = (de.scrollTop || bd.scrollTop || 0) + 5,
                axy = [xy[0] + offsets[0], xy[1] + offsets[1]],
                sz = this.getSize();

            this.anchorEl.removeClass(this.anchorCls);

            if (this.targetCounter < 2) {
                if (axy[0] < scrollX) {
                    if (this.anchorToTarget) {
                        this.defaultAlign = 'l-r';
                        if (this.mouseOffset) { this.mouseOffset[0] *= -1; }
                    }
                    this.anchor = 'left';
                    return this.getTargetXY();
                }
                if (axy[0] + sz.width > dw) {
                    if (this.anchorToTarget) {
                        this.defaultAlign = 'r-l';
                        if (this.mouseOffset) { this.mouseOffset[0] *= -1; }
                    }
                    this.anchor = 'right';
                    return this.getTargetXY();
                }
                if (axy[1] < scrollY) {
                    if (this.anchorToTarget) {
                        this.defaultAlign = 't-b';
                        if (this.mouseOffset) { this.mouseOffset[1] *= -1; }
                    }
                    this.anchor = 'top';
                    return this.getTargetXY();
                }
                if (axy[1] + sz.height > dh) {
                    if (this.anchorToTarget) {
                        this.defaultAlign = 'b-t';
                        if (this.mouseOffset) { this.mouseOffset[1] *= -1; }
                    }
                    this.anchor = 'bottom';
                    return this.getTargetXY();
                }
            }

            this.anchorCls = 'x-tip-anchor-' + this.getAnchorPosition();
            this.anchorEl.addClass(this.anchorCls);
            this.targetCounter = 0;
            return axy;
        } else {
            var mouseOffset = this.getMouseOffset();
            return [this.targetXY[0] + mouseOffset[0], this.targetXY[1] + mouseOffset[1]];
        }
    },

    getMouseOffset: function () {
        var offset = this.anchor ? [0, 0] : [15, 18];
        if (this.mouseOffset) {
            offset[0] += this.mouseOffset[0];
            offset[1] += this.mouseOffset[1];
        }
        return offset;
    },


    getAnchorPosition: function () {
        if (this.anchor) {
            this.tipAnchor = this.anchor.charAt(0);
        } else {
            var m = this.defaultAlign.match(/^([a-z]+)-([a-z]+)(\?)?$/);
            if (!m) {
                throw 'AnchorTip.defaultAlign is invalid';
            }
            this.tipAnchor = m[1].charAt(0);
        }

        switch (this.tipAnchor) {
            case 't': return 'top';
            case 'b': return 'bottom';
            case 'r': return 'right';
        }
        return 'left';
    },


    getAnchorAlign: function () {
        switch (this.anchor) {
            case 'top': return 'tl-bl';
            case 'left': return 'tl-tr';
            case 'right': return 'tr-tl';
            default: return 'bl-tl';
        }
    },


    getOffsets: function () {
        var offsets,
            ap = this.getAnchorPosition().charAt(0);
        if (this.anchorToTarget && !this.trackMouse) {
            switch (ap) {
                case 't':
                    offsets = [0, 9];
                    break;
                case 'b':
                    offsets = [0, -13];
                    break;
                case 'r':
                    offsets = [-13, 0];
                    break;
                default:
                    offsets = [9, 0];
                    break;
            }
        } else {
            switch (ap) {
                case 't':
                    offsets = [-15 - this.anchorOffset, 30];
                    break;
                case 'b':
                    offsets = [-19 - this.anchorOffset, -13 - this.el.dom.offsetHeight];
                    break;
                case 'r':
                    offsets = [-15 - this.el.dom.offsetWidth, -13 - this.anchorOffset];
                    break;
                default:
                    offsets = [25, -13 - this.anchorOffset];
                    break;
            }
        }
        var mouseOffset = this.getMouseOffset();
        offsets[0] += mouseOffset[0];
        offsets[1] += mouseOffset[1];

        return offsets;
    },


    onTargetOver: function (e) {
        if (this.disabled || e.within(this.target.dom, true)) {
            return;
        }
        var t = e.getTarget(this.delegate);
        if (t) {
            this.triggerElement = t;
            this.clearTimer('hide');
            this.targetXY = e.getXY();
            this.delayShow();
        }
    },


    delayShow: function () {
        if (this.hidden && !this.showTimer) {
            if (this.lastActive.getElapsed() < this.quickShowInterval) {
                this.show();
            } else {
                this.showTimer = this.show.defer(this.showDelay, this);
            }
        } else if (!this.hidden && this.autoHide !== false) {
            this.show();
        }
    },


    onTargetOut: function (e) {
        if (this.disabled || e.within(this.target.dom, true)) {
            return;
        }
        this.clearTimer('show');
        if (this.autoHide !== false) {
            this.delayHide();
        }
    },


    delayHide: function () {
        if (!this.hidden && !this.hideTimer) {
            this.hideTimer = this.hide.defer(this.hideDelay, this);
        }
    },


    hide: function () {
        this.clearTimer('dismiss');
        this.lastActive = new Date();
        if (this.anchorEl) {
            this.anchorEl.hide();
        }
        Ext.ToolTip.superclass.hide.call(this);
        delete this.triggerElement;
    },


    show: function () {
        if (this.anchor) {


            this.showAt([-1000, -1000]);
            this.origConstrainPosition = this.constrainPosition;
            this.constrainPosition = false;
            this.anchor = this.origAnchor;
        }
        this.showAt(this.getTargetXY());

        if (this.anchor) {
            this.anchorEl.show();
            this.syncAnchor();
            this.constrainPosition = this.origConstrainPosition;
        } else {
            this.anchorEl.hide();
        }
    },


    showAt: function (xy) {
        this.lastActive = new Date();
        this.clearTimers();
        Ext.ToolTip.superclass.showAt.call(this, xy);
        if (this.dismissDelay && this.autoHide !== false) {
            this.dismissTimer = this.hide.defer(this.dismissDelay, this);
        }
        if (this.anchor && !this.anchorEl.isVisible()) {
            this.syncAnchor();
            this.anchorEl.show();
        } else {
            this.anchorEl.hide();
        }
    },


    syncAnchor: function () {
        var anchorPos, targetPos, offset;
        switch (this.tipAnchor.charAt(0)) {
            case 't':
                anchorPos = 'b';
                targetPos = 'tl';
                offset = [20 + this.anchorOffset, 2];
                break;
            case 'r':
                anchorPos = 'l';
                targetPos = 'tr';
                offset = [-2, 11 + this.anchorOffset];
                break;
            case 'b':
                anchorPos = 't';
                targetPos = 'bl';
                offset = [20 + this.anchorOffset, -2];
                break;
            default:
                anchorPos = 'r';
                targetPos = 'tl';
                offset = [2, 11 + this.anchorOffset];
                break;
        }
        this.anchorEl.alignTo(this.el, anchorPos + '-' + targetPos, offset);
    },


    setPagePosition: function (x, y) {
        Ext.ToolTip.superclass.setPagePosition.call(this, x, y);
        if (this.anchor) {
            this.syncAnchor();
        }
    },


    clearTimer: function (name) {
        name = name + 'Timer';
        clearTimeout(this[name]);
        delete this[name];
    },


    clearTimers: function () {
        this.clearTimer('show');
        this.clearTimer('dismiss');
        this.clearTimer('hide');
    },


    onShow: function () {
        Ext.ToolTip.superclass.onShow.call(this);
        Ext.getDoc().on('mousedown', this.onDocMouseDown, this);
    },


    onHide: function () {
        Ext.ToolTip.superclass.onHide.call(this);
        Ext.getDoc().un('mousedown', this.onDocMouseDown, this);
    },


    onDocMouseDown: function (e) {
        if (this.autoHide !== true && !this.closable && !e.within(this.el.dom)) {
            this.disable();
            this.doEnable.defer(100, this);
        }
    },


    doEnable: function () {
        if (!this.isDestroyed) {
            this.enable();
        }
    },


    onDisable: function () {
        this.clearTimers();
        this.hide();
    },


    adjustPosition: function (x, y) {
        if (this.contstrainPosition) {
            var ay = this.targetXY[1], h = this.getSize().height;
            if (y <= ay && (y + h) >= ay) {
                y = ay - h - 5;
            }
        }
        return { x: x, y: y };
    },

    beforeDestroy: function () {
        this.clearTimers();
        Ext.destroy(this.anchorEl);
        delete this.anchorEl;
        delete this.target;
        delete this.anchorTarget;
        delete this.triggerElement;
        Ext.ToolTip.superclass.beforeDestroy.call(this);
    },


    onDestroy: function () {
        Ext.getDoc().un('mousedown', this.onDocMouseDown, this);
        Ext.ToolTip.superclass.onDestroy.call(this);
    }
});

Ext.reg('tooltip', Ext.ToolTip);
Ext.QuickTip = Ext.extend(Ext.ToolTip, {


    interceptTitles: false,


    tagConfig: {
        namespace: "ext",
        attribute: "qtip",
        width: "qwidth",
        target: "target",
        title: "qtitle",
        hide: "hide",
        cls: "qclass",
        align: "qalign",
        anchor: "anchor"
    },


    initComponent: function () {
        this.target = this.target || Ext.getDoc();
        this.targets = this.targets || {};
        Ext.QuickTip.superclass.initComponent.call(this);
    },


    register: function (config) {
        var cs = Ext.isArray(config) ? config : arguments;
        for (var i = 0, len = cs.length; i < len; i++) {
            var c = cs[i];
            var target = c.target;
            if (target) {
                if (Ext.isArray(target)) {
                    for (var j = 0, jlen = target.length; j < jlen; j++) {
                        this.targets[Ext.id(target[j])] = c;
                    }
                } else {
                    this.targets[Ext.id(target)] = c;
                }
            }
        }
    },


    unregister: function (el) {
        delete this.targets[Ext.id(el)];
    },


    cancelShow: function (el) {
        var at = this.activeTarget;
        el = Ext.get(el).dom;
        if (this.isVisible()) {
            if (at && at.el == el) {
                this.hide();
            }
        } else if (at && at.el == el) {
            this.clearTimer('show');
        }
    },

    getTipCfg: function (e) {
        var t = e.getTarget(),
            ttp,
            cfg;
        if (this.interceptTitles && t.title && Ext.isString(t.title)) {
            ttp = t.title;
            t.qtip = ttp;
            t.removeAttribute("title");
            e.preventDefault();
        } else {
            cfg = this.tagConfig;
            ttp = t.qtip || Ext.fly(t).getAttribute(cfg.attribute, cfg.namespace);
        }
        return ttp;
    },


    onTargetOver: function (e) {
        if (this.disabled) {
            return;
        }
        this.targetXY = e.getXY();
        var t = e.getTarget();
        if (!t || t.nodeType !== 1 || t == document || t == document.body) {
            return;
        }
        if (this.activeTarget && ((t == this.activeTarget.el) || Ext.fly(this.activeTarget.el).contains(t))) {
            this.clearTimer('hide');
            this.show();
            return;
        }
        if (t && this.targets[t.id]) {
            this.activeTarget = this.targets[t.id];
            this.activeTarget.el = t;
            this.anchor = this.activeTarget.anchor;
            if (this.anchor) {
                this.anchorTarget = t;
            }
            this.delayShow();
            return;
        }
        var ttp, et = Ext.fly(t), cfg = this.tagConfig, ns = cfg.namespace;
        if (ttp = this.getTipCfg(e)) {
            var autoHide = et.getAttribute(cfg.hide, ns);
            this.activeTarget = {
                el: t,
                text: ttp,
                width: et.getAttribute(cfg.width, ns),
                autoHide: autoHide != "user" && autoHide !== 'false',
                title: et.getAttribute(cfg.title, ns),
                cls: et.getAttribute(cfg.cls, ns),
                align: et.getAttribute(cfg.align, ns)

            };
            this.anchor = et.getAttribute(cfg.anchor, ns);
            if (this.anchor) {
                this.anchorTarget = t;
            }
            this.delayShow();
        }
    },


    onTargetOut: function (e) {


        if (this.activeTarget && e.within(this.activeTarget.el) && !this.getTipCfg(e)) {
            return;
        }

        this.clearTimer('show');
        if (this.autoHide !== false) {
            this.delayHide();
        }
    },


    showAt: function (xy) {
        var t = this.activeTarget;
        if (t) {
            if (!this.rendered) {
                this.render(Ext.getBody());
                this.activeTarget = t;
            }
            if (t.width) {
                this.setWidth(t.width);
                this.body.setWidth(this.adjustBodyWidth(t.width - this.getFrameWidth()));
                this.measureWidth = false;
            } else {
                this.measureWidth = true;
            }
            this.setTitle(t.title || '');
            this.body.update(t.text);
            this.autoHide = t.autoHide;
            this.dismissDelay = t.dismissDelay || this.dismissDelay;
            if (this.lastCls) {
                this.el.removeClass(this.lastCls);
                delete this.lastCls;
            }
            if (t.cls) {
                this.el.addClass(t.cls);
                this.lastCls = t.cls;
            }
            if (this.anchor) {
                this.constrainPosition = false;
            } else if (t.align) {
                xy = this.el.getAlignToXY(t.el, t.align);
                this.constrainPosition = false;
            } else {
                this.constrainPosition = true;
            }
        }
        Ext.QuickTip.superclass.showAt.call(this, xy);
    },


    hide: function () {
        delete this.activeTarget;
        Ext.QuickTip.superclass.hide.call(this);
    }
});
Ext.reg('quicktip', Ext.QuickTip);
Ext.QuickTips = function () {
    var tip,
        disabled = false;

    return {

        init: function (autoRender) {
            if (!tip) {
                if (!Ext.isReady) {
                    Ext.onReady(function () {
                        Ext.QuickTips.init(autoRender);
                    });
                    return;
                }
                tip = new Ext.QuickTip({
                    elements: 'header,body',
                    disabled: disabled
                });
                if (autoRender !== false) {
                    tip.render(Ext.getBody());
                }
            }
        },


        ddDisable: function () {

            if (tip && !disabled) {
                tip.disable();
            }
        },


        ddEnable: function () {

            if (tip && !disabled) {
                tip.enable();
            }
        },


        enable: function () {
            if (tip) {
                tip.enable();
            }
            disabled = false;
        },


        disable: function () {
            if (tip) {
                tip.disable();
            }
            disabled = true;
        },


        isEnabled: function () {
            return tip !== undefined && !tip.disabled;
        },


        getQuickTip: function () {
            return tip;
        },


        register: function () {
            tip.register.apply(tip, arguments);
        },


        unregister: function () {
            tip.unregister.apply(tip, arguments);
        },


        tips: function () {
            tip.register.apply(tip, arguments);
        }
    };
} ();
Ext.slider.Tip = Ext.extend(Ext.Tip, {
    minWidth: 10,
    offsets: [0, -10],

    init: function (slider) {
        slider.on({
            scope: this,
            dragstart: this.onSlide,
            drag: this.onSlide,
            dragend: this.hide,
            destroy: this.destroy
        });
    },


    onSlide: function (slider, e, thumb) {
        this.show();
        this.body.update(this.getText(thumb));
        this.doAutoWidth();
        this.el.alignTo(thumb.el, 'b-t?', this.offsets);
    },


    getText: function (thumb) {
        return String(thumb.value);
    }
});


Ext.ux.SliderTip = Ext.slider.Tip;
Ext.tree.TreePanel = Ext.extend(Ext.Panel, {
    rootVisible: true,
    animate: Ext.enableFx,
    lines: true,
    enableDD: false,
    hlDrop: Ext.enableFx,
    pathSeparator: '/',


    bubbleEvents: [],

    initComponent: function () {
        Ext.tree.TreePanel.superclass.initComponent.call(this);

        if (!this.eventModel) {
            this.eventModel = new Ext.tree.TreeEventModel(this);
        }


        var l = this.loader;
        if (!l) {
            l = new Ext.tree.TreeLoader({
                dataUrl: this.dataUrl,
                requestMethod: this.requestMethod
            });
        } else if (Ext.isObject(l) && !l.load) {
            l = new Ext.tree.TreeLoader(l);
        }
        this.loader = l;

        this.nodeHash = {};


        if (this.root) {
            var r = this.root;
            delete this.root;
            this.setRootNode(r);
        }


        this.addEvents(


           'append',

           'remove',

           'movenode',

           'insert',

           'beforeappend',

           'beforeremove',

           'beforemovenode',

            'beforeinsert',


            'beforeload',

            'load',

            'textchange',

            'beforeexpandnode',

            'beforecollapsenode',

            'expandnode',

            'disabledchange',

            'collapsenode',

            'beforeclick',

            'click',

            'containerclick',

            'checkchange',

            'beforedblclick',

            'dblclick',

            'containerdblclick',

            'contextmenu',

            'containercontextmenu',

            'beforechildrenrendered',

            'startdrag',

            'enddrag',

            'dragdrop',

            'beforenodedrop',

            'nodedrop',

            'nodedragover'
        );
        if (this.singleExpand) {
            this.on('beforeexpandnode', this.restrictExpand, this);
        }
    },


    proxyNodeEvent: function (ename, a1, a2, a3, a4, a5, a6) {
        if (ename == 'collapse' || ename == 'expand' || ename == 'beforecollapse' || ename == 'beforeexpand' || ename == 'move' || ename == 'beforemove') {
            ename = ename + 'node';
        }

        return this.fireEvent(ename, a1, a2, a3, a4, a5, a6);
    },



    getRootNode: function () {
        return this.root;
    },


    setRootNode: function (node) {
        this.destroyRoot();
        if (!node.render) {
            node = this.loader.createNode(node);
        }
        this.root = node;
        node.ownerTree = this;
        node.isRoot = true;
        this.registerNode(node);
        if (!this.rootVisible) {
            var uiP = node.attributes.uiProvider;
            node.ui = uiP ? new uiP(node) : new Ext.tree.RootTreeNodeUI(node);
        }
        if (this.innerCt) {
            this.clearInnerCt();
            this.renderRoot();
        }
        return node;
    },

    clearInnerCt: function () {
        this.innerCt.update('');
    },


    renderRoot: function () {
        this.root.render();
        if (!this.rootVisible) {
            this.root.renderChildren();
        }
    },


    getNodeById: function (id) {
        return this.nodeHash[id];
    },


    registerNode: function (node) {
        this.nodeHash[node.id] = node;
    },


    unregisterNode: function (node) {
        delete this.nodeHash[node.id];
    },


    toString: function () {
        return '[Tree' + (this.id ? ' ' + this.id : '') + ']';
    },


    restrictExpand: function (node) {
        var p = node.parentNode;
        if (p) {
            if (p.expandedChild && p.expandedChild.parentNode == p) {
                p.expandedChild.collapse();
            }
            p.expandedChild = node;
        }
    },


    getChecked: function (a, startNode) {
        startNode = startNode || this.root;
        var r = [];
        var f = function () {
            if (this.attributes.checked) {
                r.push(!a ? this : (a == 'id' ? this.id : this.attributes[a]));
            }
        };
        startNode.cascade(f);
        return r;
    },


    getLoader: function () {
        return this.loader;
    },


    expandAll: function () {
        this.root.expand(true);
    },


    collapseAll: function () {
        this.root.collapse(true);
    },


    getSelectionModel: function () {
        if (!this.selModel) {
            this.selModel = new Ext.tree.DefaultSelectionModel();
        }
        return this.selModel;
    },


    expandPath: function (path, attr, callback) {
        if (Ext.isEmpty(path)) {
            if (callback) {
                callback(false, undefined);
            }
            return;
        }
        attr = attr || 'id';
        var keys = path.split(this.pathSeparator);
        var curNode = this.root;
        if (curNode.attributes[attr] != keys[1]) {
            if (callback) {
                callback(false, null);
            }
            return;
        }
        var index = 1;
        var f = function () {
            if (++index == keys.length) {
                if (callback) {
                    callback(true, curNode);
                }
                return;
            }
            var c = curNode.findChild(attr, keys[index]);
            if (!c) {
                if (callback) {
                    callback(false, curNode);
                }
                return;
            }
            curNode = c;
            c.expand(false, false, f);
        };
        curNode.expand(false, false, f);
    },


    selectPath: function (path, attr, callback) {
        if (Ext.isEmpty(path)) {
            if (callback) {
                callback(false, undefined);
            }
            return;
        }
        attr = attr || 'id';
        var keys = path.split(this.pathSeparator),
            v = keys.pop();
        if (keys.length > 1) {
            var f = function (success, node) {
                if (success && node) {
                    var n = node.findChild(attr, v);
                    if (n) {
                        n.select();
                        if (callback) {
                            callback(true, n);
                        }
                    } else if (callback) {
                        callback(false, n);
                    }
                } else {
                    if (callback) {
                        callback(false, n);
                    }
                }
            };
            this.expandPath(keys.join(this.pathSeparator), attr, f);
        } else {
            this.root.select();
            if (callback) {
                callback(true, this.root);
            }
        }
    },


    getTreeEl: function () {
        return this.body;
    },


    onRender: function (ct, position) {
        Ext.tree.TreePanel.superclass.onRender.call(this, ct, position);
        this.el.addClass('x-tree');
        this.innerCt = this.body.createChild({ tag: 'ul',
            cls: 'x-tree-root-ct ' +
               (this.useArrows ? 'x-tree-arrows' : this.lines ? 'x-tree-lines' : 'x-tree-no-lines')
        });
    },


    initEvents: function () {
        Ext.tree.TreePanel.superclass.initEvents.call(this);

        if (this.containerScroll) {
            Ext.dd.ScrollManager.register(this.body);
        }
        if ((this.enableDD || this.enableDrop) && !this.dropZone) {

            this.dropZone = new Ext.tree.TreeDropZone(this, this.dropConfig || {
                ddGroup: this.ddGroup || 'TreeDD', appendOnly: this.ddAppendOnly === true
            });
        }
        if ((this.enableDD || this.enableDrag) && !this.dragZone) {

            this.dragZone = new Ext.tree.TreeDragZone(this, this.dragConfig || {
                ddGroup: this.ddGroup || 'TreeDD',
                scroll: this.ddScroll
            });
        }
        this.getSelectionModel().init(this);
    },


    afterRender: function () {
        Ext.tree.TreePanel.superclass.afterRender.call(this);
        this.renderRoot();
    },

    beforeDestroy: function () {
        if (this.rendered) {
            Ext.dd.ScrollManager.unregister(this.body);
            Ext.destroy(this.dropZone, this.dragZone);
        }
        this.destroyRoot();
        Ext.destroy(this.loader);
        this.nodeHash = this.root = this.loader = null;
        Ext.tree.TreePanel.superclass.beforeDestroy.call(this);
    },


    destroyRoot: function () {
        if (this.root && this.root.destroy) {
            this.root.destroy(true);
        }
    }



















































});

Ext.tree.TreePanel.nodeTypes = {};

Ext.reg('treepanel', Ext.tree.TreePanel); Ext.tree.TreeEventModel = function (tree) {
    this.tree = tree;
    this.tree.on('render', this.initEvents, this);
};

Ext.tree.TreeEventModel.prototype = {
    initEvents: function () {
        var t = this.tree;

        if (t.trackMouseOver !== false) {
            t.mon(t.innerCt, {
                scope: this,
                mouseover: this.delegateOver,
                mouseout: this.delegateOut
            });
        }
        t.mon(t.getTreeEl(), {
            scope: this,
            click: this.delegateClick,
            dblclick: this.delegateDblClick,
            contextmenu: this.delegateContextMenu
        });
    },

    getNode: function (e) {
        var t;
        if (t = e.getTarget('.x-tree-node-el', 10)) {
            var id = Ext.fly(t, '_treeEvents').getAttribute('tree-node-id', 'ext');
            if (id) {
                return this.tree.getNodeById(id);
            }
        }
        return null;
    },

    getNodeTarget: function (e) {
        var t = e.getTarget('.x-tree-node-icon', 1);
        if (!t) {
            t = e.getTarget('.x-tree-node-el', 6);
        }
        return t;
    },

    delegateOut: function (e, t) {
        if (!this.beforeEvent(e)) {
            return;
        }
        if (e.getTarget('.x-tree-ec-icon', 1)) {
            var n = this.getNode(e);
            this.onIconOut(e, n);
            if (n == this.lastEcOver) {
                delete this.lastEcOver;
            }
        }
        if ((t = this.getNodeTarget(e)) && !e.within(t, true)) {
            this.onNodeOut(e, this.getNode(e));
        }
    },

    delegateOver: function (e, t) {
        if (!this.beforeEvent(e)) {
            return;
        }
        if (Ext.isGecko && !this.trackingDoc) {
            Ext.getBody().on('mouseover', this.trackExit, this);
            this.trackingDoc = true;
        }
        if (this.lastEcOver) {
            this.onIconOut(e, this.lastEcOver);
            delete this.lastEcOver;
        }
        if (e.getTarget('.x-tree-ec-icon', 1)) {
            this.lastEcOver = this.getNode(e);
            this.onIconOver(e, this.lastEcOver);
        }
        if (t = this.getNodeTarget(e)) {
            this.onNodeOver(e, this.getNode(e));
        }
    },

    trackExit: function (e) {
        if (this.lastOverNode) {
            if (this.lastOverNode.ui && !e.within(this.lastOverNode.ui.getEl())) {
                this.onNodeOut(e, this.lastOverNode);
            }
            delete this.lastOverNode;
            Ext.getBody().un('mouseover', this.trackExit, this);
            this.trackingDoc = false;
        }

    },

    delegateClick: function (e, t) {
        if (this.beforeEvent(e)) {
            if (e.getTarget('input[type=checkbox]', 1)) {
                this.onCheckboxClick(e, this.getNode(e));
            } else if (e.getTarget('.x-tree-ec-icon', 1)) {
                this.onIconClick(e, this.getNode(e));
            } else if (this.getNodeTarget(e)) {
                this.onNodeClick(e, this.getNode(e));
            }
        } else {
            this.checkContainerEvent(e, 'click');
        }
    },

    delegateDblClick: function (e, t) {
        if (this.beforeEvent(e)) {
            if (this.getNodeTarget(e)) {
                this.onNodeDblClick(e, this.getNode(e));
            }
        } else {
            this.checkContainerEvent(e, 'dblclick');
        }
    },

    delegateContextMenu: function (e, t) {
        if (this.beforeEvent(e)) {
            if (this.getNodeTarget(e)) {
                this.onNodeContextMenu(e, this.getNode(e));
            }
        } else {
            this.checkContainerEvent(e, 'contextmenu');
        }
    },

    checkContainerEvent: function (e, type) {
        if (this.disabled) {
            e.stopEvent();
            return false;
        }
        this.onContainerEvent(e, type);
    },

    onContainerEvent: function (e, type) {
        this.tree.fireEvent('container' + type, this.tree, e);
    },

    onNodeClick: function (e, node) {
        node.ui.onClick(e);
    },

    onNodeOver: function (e, node) {
        this.lastOverNode = node;
        node.ui.onOver(e);
    },

    onNodeOut: function (e, node) {
        node.ui.onOut(e);
    },

    onIconOver: function (e, node) {
        node.ui.addClass('x-tree-ec-over');
    },

    onIconOut: function (e, node) {
        node.ui.removeClass('x-tree-ec-over');
    },

    onIconClick: function (e, node) {
        node.ui.ecClick(e);
    },

    onCheckboxClick: function (e, node) {
        node.ui.onCheckChange(e);
    },

    onNodeDblClick: function (e, node) {
        node.ui.onDblClick(e);
    },

    onNodeContextMenu: function (e, node) {
        node.ui.onContextMenu(e);
    },

    beforeEvent: function (e) {
        var node = this.getNode(e);
        if (this.disabled || !node || !node.ui) {
            e.stopEvent();
            return false;
        }
        return true;
    },

    disable: function () {
        this.disabled = true;
    },

    enable: function () {
        this.disabled = false;
    }
};
Ext.tree.DefaultSelectionModel = Ext.extend(Ext.util.Observable, {

    constructor: function (config) {
        this.selNode = null;

        this.addEvents(

            'selectionchange',


            'beforeselect'
        );

        Ext.apply(this, config);
        Ext.tree.DefaultSelectionModel.superclass.constructor.call(this);
    },

    init: function (tree) {
        this.tree = tree;
        tree.mon(tree.getTreeEl(), 'keydown', this.onKeyDown, this);
        tree.on('click', this.onNodeClick, this);
    },

    onNodeClick: function (node, e) {
        this.select(node);
    },


    select: function (node, selectNextNode) {

        if (!Ext.fly(node.ui.wrap).isVisible() && selectNextNode) {
            return selectNextNode.call(this, node);
        }
        var last = this.selNode;
        if (node == last) {
            node.ui.onSelectedChange(true);
        } else if (this.fireEvent('beforeselect', this, node, last) !== false) {
            if (last && last.ui) {
                last.ui.onSelectedChange(false);
            }
            this.selNode = node;
            node.ui.onSelectedChange(true);
            this.fireEvent('selectionchange', this, node, last);
        }
        return node;
    },


    unselect: function (node, silent) {
        if (this.selNode == node) {
            this.clearSelections(silent);
        }
    },


    clearSelections: function (silent) {
        var n = this.selNode;
        if (n) {
            n.ui.onSelectedChange(false);
            this.selNode = null;
            if (silent !== true) {
                this.fireEvent('selectionchange', this, null);
            }
        }
        return n;
    },


    getSelectedNode: function () {
        return this.selNode;
    },


    isSelected: function (node) {
        return this.selNode == node;
    },


    selectPrevious: function (s) {
        if (!(s = s || this.selNode || this.lastSelNode)) {
            return null;
        }

        var ps = s.previousSibling;
        if (ps) {
            if (!ps.isExpanded() || ps.childNodes.length < 1) {
                return this.select(ps, this.selectPrevious);
            } else {
                var lc = ps.lastChild;
                while (lc && lc.isExpanded() && Ext.fly(lc.ui.wrap).isVisible() && lc.childNodes.length > 0) {
                    lc = lc.lastChild;
                }
                return this.select(lc, this.selectPrevious);
            }
        } else if (s.parentNode && (this.tree.rootVisible || !s.parentNode.isRoot)) {
            return this.select(s.parentNode, this.selectPrevious);
        }
        return null;
    },


    selectNext: function (s) {
        if (!(s = s || this.selNode || this.lastSelNode)) {
            return null;
        }

        if (s.firstChild && s.isExpanded() && Ext.fly(s.ui.wrap).isVisible()) {
            return this.select(s.firstChild, this.selectNext);
        } else if (s.nextSibling) {
            return this.select(s.nextSibling, this.selectNext);
        } else if (s.parentNode) {
            var newS = null;
            s.parentNode.bubble(function () {
                if (this.nextSibling) {
                    newS = this.getOwnerTree().selModel.select(this.nextSibling, this.selectNext);
                    return false;
                }
            });
            return newS;
        }
        return null;
    },

    onKeyDown: function (e) {
        var s = this.selNode || this.lastSelNode;

        var sm = this;
        if (!s) {
            return;
        }
        var k = e.getKey();
        switch (k) {
            case e.DOWN:
                e.stopEvent();
                this.selectNext();
                break;
            case e.UP:
                e.stopEvent();
                this.selectPrevious();
                break;
            case e.RIGHT:
                e.preventDefault();
                if (s.hasChildNodes()) {
                    if (!s.isExpanded()) {
                        s.expand();
                    } else if (s.firstChild) {
                        this.select(s.firstChild, e);
                    }
                }
                break;
            case e.LEFT:
                e.preventDefault();
                if (s.hasChildNodes() && s.isExpanded()) {
                    s.collapse();
                } else if (s.parentNode && (this.tree.rootVisible || s.parentNode != this.tree.getRootNode())) {
                    this.select(s.parentNode, e);
                }
                break;
        };
    }
});


Ext.tree.MultiSelectionModel = Ext.extend(Ext.util.Observable, {

    constructor: function (config) {
        this.selNodes = [];
        this.selMap = {};
        this.addEvents(

            'selectionchange'
        );
        Ext.apply(this, config);
        Ext.tree.MultiSelectionModel.superclass.constructor.call(this);
    },

    init: function (tree) {
        this.tree = tree;
        tree.mon(tree.getTreeEl(), 'keydown', this.onKeyDown, this);
        tree.on('click', this.onNodeClick, this);
    },

    onNodeClick: function (node, e) {
        if (e.ctrlKey && this.isSelected(node)) {
            this.unselect(node);
        } else {
            this.select(node, e, e.ctrlKey);
        }
    },


    select: function (node, e, keepExisting) {
        if (keepExisting !== true) {
            this.clearSelections(true);
        }
        if (this.isSelected(node)) {
            this.lastSelNode = node;
            return node;
        }
        this.selNodes.push(node);
        this.selMap[node.id] = node;
        this.lastSelNode = node;
        node.ui.onSelectedChange(true);
        this.fireEvent('selectionchange', this, this.selNodes);
        return node;
    },


    unselect: function (node) {
        if (this.selMap[node.id]) {
            node.ui.onSelectedChange(false);
            var sn = this.selNodes;
            var index = sn.indexOf(node);
            if (index != -1) {
                this.selNodes.splice(index, 1);
            }
            delete this.selMap[node.id];
            this.fireEvent('selectionchange', this, this.selNodes);
        }
    },


    clearSelections: function (suppressEvent) {
        var sn = this.selNodes;
        if (sn.length > 0) {
            for (var i = 0, len = sn.length; i < len; i++) {
                sn[i].ui.onSelectedChange(false);
            }
            this.selNodes = [];
            this.selMap = {};
            if (suppressEvent !== true) {
                this.fireEvent('selectionchange', this, this.selNodes);
            }
        }
    },


    isSelected: function (node) {
        return this.selMap[node.id] ? true : false;
    },


    getSelectedNodes: function () {
        return this.selNodes.concat([]);
    },

    onKeyDown: Ext.tree.DefaultSelectionModel.prototype.onKeyDown,

    selectNext: Ext.tree.DefaultSelectionModel.prototype.selectNext,

    selectPrevious: Ext.tree.DefaultSelectionModel.prototype.selectPrevious
});
Ext.data.Tree = Ext.extend(Ext.util.Observable, {

    constructor: function (root) {
        this.nodeHash = {};

        this.root = null;
        if (root) {
            this.setRootNode(root);
        }
        this.addEvents(

            "append",

            "remove",

            "move",

            "insert",

            "beforeappend",

            "beforeremove",

            "beforemove",

            "beforeinsert"
        );
        Ext.data.Tree.superclass.constructor.call(this);
    },


    pathSeparator: "/",


    proxyNodeEvent: function () {
        return this.fireEvent.apply(this, arguments);
    },


    getRootNode: function () {
        return this.root;
    },


    setRootNode: function (node) {
        this.root = node;
        node.ownerTree = this;
        node.isRoot = true;
        this.registerNode(node);
        return node;
    },


    getNodeById: function (id) {
        return this.nodeHash[id];
    },


    registerNode: function (node) {
        this.nodeHash[node.id] = node;
    },


    unregisterNode: function (node) {
        delete this.nodeHash[node.id];
    },

    toString: function () {
        return "[Tree" + (this.id ? " " + this.id : "") + "]";
    }
});


Ext.data.Node = Ext.extend(Ext.util.Observable, {

    constructor: function (attributes) {

        this.attributes = attributes || {};
        this.leaf = this.attributes.leaf;

        this.id = this.attributes.id;
        if (!this.id) {
            this.id = Ext.id(null, "xnode-");
            this.attributes.id = this.id;
        }

        this.childNodes = [];

        this.parentNode = null;

        this.firstChild = null;

        this.lastChild = null;

        this.previousSibling = null;

        this.nextSibling = null;

        this.addEvents({

            "append": true,

            "remove": true,

            "move": true,

            "insert": true,

            "beforeappend": true,

            "beforeremove": true,

            "beforemove": true,

            "beforeinsert": true
        });
        this.listeners = this.attributes.listeners;
        Ext.data.Node.superclass.constructor.call(this);
    },


    fireEvent: function (evtName) {

        if (Ext.data.Node.superclass.fireEvent.apply(this, arguments) === false) {
            return false;
        }

        var ot = this.getOwnerTree();
        if (ot) {
            if (ot.proxyNodeEvent.apply(ot, arguments) === false) {
                return false;
            }
        }
        return true;
    },


    isLeaf: function () {
        return this.leaf === true;
    },


    setFirstChild: function (node) {
        this.firstChild = node;
    },


    setLastChild: function (node) {
        this.lastChild = node;
    },



    isLast: function () {
        return (!this.parentNode ? true : this.parentNode.lastChild == this);
    },


    isFirst: function () {
        return (!this.parentNode ? true : this.parentNode.firstChild == this);
    },


    hasChildNodes: function () {
        return !this.isLeaf() && this.childNodes.length > 0;
    },


    isExpandable: function () {
        return this.attributes.expandable || this.hasChildNodes();
    },


    appendChild: function (node) {
        var multi = false;
        if (Ext.isArray(node)) {
            multi = node;
        } else if (arguments.length > 1) {
            multi = arguments;
        }

        if (multi) {
            for (var i = 0, len = multi.length; i < len; i++) {
                this.appendChild(multi[i]);
            }
        } else {
            if (this.fireEvent("beforeappend", this.ownerTree, this, node) === false) {
                return false;
            }
            var index = this.childNodes.length;
            var oldParent = node.parentNode;

            if (oldParent) {
                if (node.fireEvent("beforemove", node.getOwnerTree(), node, oldParent, this, index) === false) {
                    return false;
                }
                oldParent.removeChild(node);
            }
            index = this.childNodes.length;
            if (index === 0) {
                this.setFirstChild(node);
            }
            this.childNodes.push(node);
            node.parentNode = this;
            var ps = this.childNodes[index - 1];
            if (ps) {
                node.previousSibling = ps;
                ps.nextSibling = node;
            } else {
                node.previousSibling = null;
            }
            node.nextSibling = null;
            this.setLastChild(node);
            node.setOwnerTree(this.getOwnerTree());
            this.fireEvent("append", this.ownerTree, this, node, index);
            if (oldParent) {
                node.fireEvent("move", this.ownerTree, node, oldParent, this, index);
            }
            return node;
        }
    },


    removeChild: function (node, destroy) {
        var index = this.childNodes.indexOf(node);
        if (index == -1) {
            return false;
        }
        if (this.fireEvent("beforeremove", this.ownerTree, this, node) === false) {
            return false;
        }


        this.childNodes.splice(index, 1);


        if (node.previousSibling) {
            node.previousSibling.nextSibling = node.nextSibling;
        }
        if (node.nextSibling) {
            node.nextSibling.previousSibling = node.previousSibling;
        }


        if (this.firstChild == node) {
            this.setFirstChild(node.nextSibling);
        }
        if (this.lastChild == node) {
            this.setLastChild(node.previousSibling);
        }

        this.fireEvent("remove", this.ownerTree, this, node);
        if (destroy) {
            node.destroy(true);
        } else {
            node.clear();
        }
        return node;
    },


    clear: function (destroy) {

        this.setOwnerTree(null, destroy);
        this.parentNode = this.previousSibling = this.nextSibling = null;
        if (destroy) {
            this.firstChild = this.lastChild = null;
        }
    },


    destroy: function (silent) {

        if (silent === true) {
            this.purgeListeners();
            this.clear(true);
            Ext.each(this.childNodes, function (n) {
                n.destroy(true);
            });
            this.childNodes = null;
        } else {
            this.remove(true);
        }
    },


    insertBefore: function (node, refNode) {
        if (!refNode) {
            return this.appendChild(node);
        }

        if (node == refNode) {
            return false;
        }

        if (this.fireEvent("beforeinsert", this.ownerTree, this, node, refNode) === false) {
            return false;
        }
        var index = this.childNodes.indexOf(refNode);
        var oldParent = node.parentNode;
        var refIndex = index;


        if (oldParent == this && this.childNodes.indexOf(node) < index) {
            refIndex--;
        }


        if (oldParent) {
            if (node.fireEvent("beforemove", node.getOwnerTree(), node, oldParent, this, index, refNode) === false) {
                return false;
            }
            oldParent.removeChild(node);
        }
        if (refIndex === 0) {
            this.setFirstChild(node);
        }
        this.childNodes.splice(refIndex, 0, node);
        node.parentNode = this;
        var ps = this.childNodes[refIndex - 1];
        if (ps) {
            node.previousSibling = ps;
            ps.nextSibling = node;
        } else {
            node.previousSibling = null;
        }
        node.nextSibling = refNode;
        refNode.previousSibling = node;
        node.setOwnerTree(this.getOwnerTree());
        this.fireEvent("insert", this.ownerTree, this, node, refNode);
        if (oldParent) {
            node.fireEvent("move", this.ownerTree, node, oldParent, this, refIndex, refNode);
        }
        return node;
    },


    remove: function (destroy) {
        if (this.parentNode) {
            this.parentNode.removeChild(this, destroy);
        }
        return this;
    },


    removeAll: function (destroy) {
        var cn = this.childNodes,
            n;
        while ((n = cn[0])) {
            this.removeChild(n, destroy);
        }
        return this;
    },


    item: function (index) {
        return this.childNodes[index];
    },


    replaceChild: function (newChild, oldChild) {
        var s = oldChild ? oldChild.nextSibling : null;
        this.removeChild(oldChild);
        this.insertBefore(newChild, s);
        return oldChild;
    },


    indexOf: function (child) {
        return this.childNodes.indexOf(child);
    },


    getOwnerTree: function () {

        if (!this.ownerTree) {
            var p = this;
            while (p) {
                if (p.ownerTree) {
                    this.ownerTree = p.ownerTree;
                    break;
                }
                p = p.parentNode;
            }
        }
        return this.ownerTree;
    },


    getDepth: function () {
        var depth = 0;
        var p = this;
        while (p.parentNode) {
            ++depth;
            p = p.parentNode;
        }
        return depth;
    },


    setOwnerTree: function (tree, destroy) {

        if (tree != this.ownerTree) {
            if (this.ownerTree) {
                this.ownerTree.unregisterNode(this);
            }
            this.ownerTree = tree;

            if (destroy !== true) {
                Ext.each(this.childNodes, function (n) {
                    n.setOwnerTree(tree);
                });
            }
            if (tree) {
                tree.registerNode(this);
            }
        }
    },


    setId: function (id) {
        if (id !== this.id) {
            var t = this.ownerTree;
            if (t) {
                t.unregisterNode(this);
            }
            this.id = this.attributes.id = id;
            if (t) {
                t.registerNode(this);
            }
            this.onIdChange(id);
        }
    },


    onIdChange: Ext.emptyFn,


    getPath: function (attr) {
        attr = attr || "id";
        var p = this.parentNode;
        var b = [this.attributes[attr]];
        while (p) {
            b.unshift(p.attributes[attr]);
            p = p.parentNode;
        }
        var sep = this.getOwnerTree().pathSeparator;
        return sep + b.join(sep);
    },


    bubble: function (fn, scope, args) {
        var p = this;
        while (p) {
            if (fn.apply(scope || p, args || [p]) === false) {
                break;
            }
            p = p.parentNode;
        }
    },


    cascade: function (fn, scope, args) {
        if (fn.apply(scope || this, args || [this]) !== false) {
            var cs = this.childNodes;
            for (var i = 0, len = cs.length; i < len; i++) {
                cs[i].cascade(fn, scope, args);
            }
        }
    },


    eachChild: function (fn, scope, args) {
        var cs = this.childNodes;
        for (var i = 0, len = cs.length; i < len; i++) {
            if (fn.apply(scope || cs[i], args || [cs[i]]) === false) {
                break;
            }
        }
    },


    findChild: function (attribute, value, deep) {
        return this.findChildBy(function () {
            return this.attributes[attribute] == value;
        }, null, deep);
    },


    findChildBy: function (fn, scope, deep) {
        var cs = this.childNodes,
            len = cs.length,
            i = 0,
            n,
            res;
        for (; i < len; i++) {
            n = cs[i];
            if (fn.call(scope || n, n) === true) {
                return n;
            } else if (deep) {
                res = n.findChildBy(fn, scope, deep);
                if (res != null) {
                    return res;
                }
            }

        }
        return null;
    },


    sort: function (fn, scope) {
        var cs = this.childNodes;
        var len = cs.length;
        if (len > 0) {
            var sortFn = scope ? function () { fn.apply(scope, arguments); } : fn;
            cs.sort(sortFn);
            for (var i = 0; i < len; i++) {
                var n = cs[i];
                n.previousSibling = cs[i - 1];
                n.nextSibling = cs[i + 1];
                if (i === 0) {
                    this.setFirstChild(n);
                }
                if (i == len - 1) {
                    this.setLastChild(n);
                }
            }
        }
    },


    contains: function (node) {
        return node.isAncestor(this);
    },


    isAncestor: function (node) {
        var p = this.parentNode;
        while (p) {
            if (p == node) {
                return true;
            }
            p = p.parentNode;
        }
        return false;
    },

    toString: function () {
        return "[Node" + (this.id ? " " + this.id : "") + "]";
    }
});
Ext.tree.TreeNode = Ext.extend(Ext.data.Node, {

    constructor: function (attributes) {
        attributes = attributes || {};
        if (Ext.isString(attributes)) {
            attributes = { text: attributes };
        }
        this.childrenRendered = false;
        this.rendered = false;
        Ext.tree.TreeNode.superclass.constructor.call(this, attributes);
        this.expanded = attributes.expanded === true;
        this.isTarget = attributes.isTarget !== false;
        this.draggable = attributes.draggable !== false && attributes.allowDrag !== false;
        this.allowChildren = attributes.allowChildren !== false && attributes.allowDrop !== false;


        this.text = attributes.text;

        this.disabled = attributes.disabled === true;

        this.hidden = attributes.hidden === true;

        this.addEvents(

            'textchange',

            'beforeexpand',

            'beforecollapse',

            'expand',

            'disabledchange',

            'collapse',

            'beforeclick',

            'click',

            'checkchange',

            'beforedblclick',

            'dblclick',

            'contextmenu',

            'beforechildrenrendered'
        );

        var uiClass = this.attributes.uiProvider || this.defaultUI || Ext.tree.TreeNodeUI;


        this.ui = new uiClass(this);
    },

    preventHScroll: true,

    isExpanded: function () {
        return this.expanded;
    },


    getUI: function () {
        return this.ui;
    },

    getLoader: function () {
        var owner;
        return this.loader || ((owner = this.getOwnerTree()) && owner.loader ? owner.loader : (this.loader = new Ext.tree.TreeLoader()));
    },


    setFirstChild: function (node) {
        var of = this.firstChild;
        Ext.tree.TreeNode.superclass.setFirstChild.call(this, node);
        if (this.childrenRendered && of && node != of) {
            of.renderIndent(true, true);
        }
        if (this.rendered) {
            this.renderIndent(true, true);
        }
    },


    setLastChild: function (node) {
        var ol = this.lastChild;
        Ext.tree.TreeNode.superclass.setLastChild.call(this, node);
        if (this.childrenRendered && ol && node != ol) {
            ol.renderIndent(true, true);
        }
        if (this.rendered) {
            this.renderIndent(true, true);
        }
    },



    appendChild: function (n) {
        if (!n.render && !Ext.isArray(n)) {
            n = this.getLoader().createNode(n);
        }
        var node = Ext.tree.TreeNode.superclass.appendChild.call(this, n);
        if (node && this.childrenRendered) {
            node.render();
        }
        this.ui.updateExpandIcon();
        return node;
    },


    removeChild: function (node, destroy) {
        this.ownerTree.getSelectionModel().unselect(node);
        Ext.tree.TreeNode.superclass.removeChild.apply(this, arguments);

        if (!destroy) {
            var rendered = node.ui.rendered;

            if (rendered) {
                node.ui.remove();
            }
            if (rendered && this.childNodes.length < 1) {
                this.collapse(false, false);
            } else {
                this.ui.updateExpandIcon();
            }
            if (!this.firstChild && !this.isHiddenRoot()) {
                this.childrenRendered = false;
            }
        }
        return node;
    },


    insertBefore: function (node, refNode) {
        if (!node.render) {
            node = this.getLoader().createNode(node);
        }
        var newNode = Ext.tree.TreeNode.superclass.insertBefore.call(this, node, refNode);
        if (newNode && refNode && this.childrenRendered) {
            node.render();
        }
        this.ui.updateExpandIcon();
        return newNode;
    },


    setText: function (text) {
        var oldText = this.text;
        this.text = this.attributes.text = text;
        if (this.rendered) {
            this.ui.onTextChange(this, text, oldText);
        }
        this.fireEvent('textchange', this, text, oldText);
    },


    setIconCls: function (cls) {
        var old = this.attributes.iconCls;
        this.attributes.iconCls = cls;
        if (this.rendered) {
            this.ui.onIconClsChange(this, cls, old);
        }
    },


    setTooltip: function (tip, title) {
        this.attributes.qtip = tip;
        this.attributes.qtipTitle = title;
        if (this.rendered) {
            this.ui.onTipChange(this, tip, title);
        }
    },


    setIcon: function (icon) {
        this.attributes.icon = icon;
        if (this.rendered) {
            this.ui.onIconChange(this, icon);
        }
    },


    setHref: function (href, target) {
        this.attributes.href = href;
        this.attributes.hrefTarget = target;
        if (this.rendered) {
            this.ui.onHrefChange(this, href, target);
        }
    },


    setCls: function (cls) {
        var old = this.attributes.cls;
        this.attributes.cls = cls;
        if (this.rendered) {
            this.ui.onClsChange(this, cls, old);
        }
    },


    select: function () {
        var t = this.getOwnerTree();
        if (t) {
            t.getSelectionModel().select(this);
        }
    },


    unselect: function (silent) {
        var t = this.getOwnerTree();
        if (t) {
            t.getSelectionModel().unselect(this, silent);
        }
    },


    isSelected: function () {
        var t = this.getOwnerTree();
        return t ? t.getSelectionModel().isSelected(this) : false;
    },


    expand: function (deep, anim, callback, scope) {
        if (!this.expanded) {
            if (this.fireEvent('beforeexpand', this, deep, anim) === false) {
                return;
            }
            if (!this.childrenRendered) {
                this.renderChildren();
            }
            this.expanded = true;
            if (!this.isHiddenRoot() && (this.getOwnerTree().animate && anim !== false) || anim) {
                this.ui.animExpand(function () {
                    this.fireEvent('expand', this);
                    this.runCallback(callback, scope || this, [this]);
                    if (deep === true) {
                        this.expandChildNodes(true, true);
                    }
                } .createDelegate(this));
                return;
            } else {
                this.ui.expand();
                this.fireEvent('expand', this);
                this.runCallback(callback, scope || this, [this]);
            }
        } else {
            this.runCallback(callback, scope || this, [this]);
        }
        if (deep === true) {
            this.expandChildNodes(true);
        }
    },

    runCallback: function (cb, scope, args) {
        if (Ext.isFunction(cb)) {
            cb.apply(scope, args);
        }
    },

    isHiddenRoot: function () {
        return this.isRoot && !this.getOwnerTree().rootVisible;
    },


    collapse: function (deep, anim, callback, scope) {
        if (this.expanded && !this.isHiddenRoot()) {
            if (this.fireEvent('beforecollapse', this, deep, anim) === false) {
                return;
            }
            this.expanded = false;
            if ((this.getOwnerTree().animate && anim !== false) || anim) {
                this.ui.animCollapse(function () {
                    this.fireEvent('collapse', this);
                    this.runCallback(callback, scope || this, [this]);
                    if (deep === true) {
                        this.collapseChildNodes(true);
                    }
                } .createDelegate(this));
                return;
            } else {
                this.ui.collapse();
                this.fireEvent('collapse', this);
                this.runCallback(callback, scope || this, [this]);
            }
        } else if (!this.expanded) {
            this.runCallback(callback, scope || this, [this]);
        }
        if (deep === true) {
            var cs = this.childNodes;
            for (var i = 0, len = cs.length; i < len; i++) {
                cs[i].collapse(true, false);
            }
        }
    },


    delayedExpand: function (delay) {
        if (!this.expandProcId) {
            this.expandProcId = this.expand.defer(delay, this);
        }
    },


    cancelExpand: function () {
        if (this.expandProcId) {
            clearTimeout(this.expandProcId);
        }
        this.expandProcId = false;
    },


    toggle: function () {
        if (this.expanded) {
            this.collapse();
        } else {
            this.expand();
        }
    },


    ensureVisible: function (callback, scope) {
        var tree = this.getOwnerTree();
        tree.expandPath(this.parentNode ? this.parentNode.getPath() : this.getPath(), false, function () {
            var node = tree.getNodeById(this.id);
            tree.getTreeEl().scrollChildIntoView(node.ui.anchor);
            this.runCallback(callback, scope || this, [this]);
        } .createDelegate(this));
    },


    expandChildNodes: function (deep, anim) {
        var cs = this.childNodes,
            i,
            len = cs.length;
        for (i = 0; i < len; i++) {
            cs[i].expand(deep, anim);
        }
    },


    collapseChildNodes: function (deep) {
        var cs = this.childNodes;
        for (var i = 0, len = cs.length; i < len; i++) {
            cs[i].collapse(deep);
        }
    },


    disable: function () {
        this.disabled = true;
        this.unselect();
        if (this.rendered && this.ui.onDisableChange) {
            this.ui.onDisableChange(this, true);
        }
        this.fireEvent('disabledchange', this, true);
    },


    enable: function () {
        this.disabled = false;
        if (this.rendered && this.ui.onDisableChange) {
            this.ui.onDisableChange(this, false);
        }
        this.fireEvent('disabledchange', this, false);
    },


    renderChildren: function (suppressEvent) {
        if (suppressEvent !== false) {
            this.fireEvent('beforechildrenrendered', this);
        }
        var cs = this.childNodes;
        for (var i = 0, len = cs.length; i < len; i++) {
            cs[i].render(true);
        }
        this.childrenRendered = true;
    },


    sort: function (fn, scope) {
        Ext.tree.TreeNode.superclass.sort.apply(this, arguments);
        if (this.childrenRendered) {
            var cs = this.childNodes;
            for (var i = 0, len = cs.length; i < len; i++) {
                cs[i].render(true);
            }
        }
    },


    render: function (bulkRender) {
        this.ui.render(bulkRender);
        if (!this.rendered) {

            this.getOwnerTree().registerNode(this);
            this.rendered = true;
            if (this.expanded) {
                this.expanded = false;
                this.expand(false, false);
            }
        }
    },


    renderIndent: function (deep, refresh) {
        if (refresh) {
            this.ui.childIndent = null;
        }
        this.ui.renderIndent();
        if (deep === true && this.childrenRendered) {
            var cs = this.childNodes;
            for (var i = 0, len = cs.length; i < len; i++) {
                cs[i].renderIndent(true, refresh);
            }
        }
    },

    beginUpdate: function () {
        this.childrenRendered = false;
    },

    endUpdate: function () {
        if (this.expanded && this.rendered) {
            this.renderChildren();
        }
    },


    destroy: function (silent) {
        if (silent === true) {
            this.unselect(true);
        }
        Ext.tree.TreeNode.superclass.destroy.call(this, silent);
        Ext.destroy(this.ui, this.loader);
        this.ui = this.loader = null;
    },


    onIdChange: function (id) {
        this.ui.onIdChange(id);
    }
});

Ext.tree.TreePanel.nodeTypes.node = Ext.tree.TreeNode;
Ext.tree.AsyncTreeNode = function (config) {
    this.loaded = config && config.loaded === true;
    this.loading = false;
    Ext.tree.AsyncTreeNode.superclass.constructor.apply(this, arguments);

    this.addEvents('beforeload', 'load');


};
Ext.extend(Ext.tree.AsyncTreeNode, Ext.tree.TreeNode, {
    expand: function (deep, anim, callback, scope) {
        if (this.loading) {
            var timer;
            var f = function () {
                if (!this.loading) {
                    clearInterval(timer);
                    this.expand(deep, anim, callback, scope);
                }
            } .createDelegate(this);
            timer = setInterval(f, 200);
            return;
        }
        if (!this.loaded) {
            if (this.fireEvent("beforeload", this) === false) {
                return;
            }
            this.loading = true;
            this.ui.beforeLoad(this);
            var loader = this.loader || this.attributes.loader || this.getOwnerTree().getLoader();
            if (loader) {
                loader.load(this, this.loadComplete.createDelegate(this, [deep, anim, callback, scope]), this);
                return;
            }
        }
        Ext.tree.AsyncTreeNode.superclass.expand.call(this, deep, anim, callback, scope);
    },


    isLoading: function () {
        return this.loading;
    },

    loadComplete: function (deep, anim, callback, scope) {
        this.loading = false;
        this.loaded = true;
        this.ui.afterLoad(this);
        this.fireEvent("load", this);
        this.expand(deep, anim, callback, scope);
    },


    isLoaded: function () {
        return this.loaded;
    },

    hasChildNodes: function () {
        if (!this.isLeaf() && !this.loaded) {
            return true;
        } else {
            return Ext.tree.AsyncTreeNode.superclass.hasChildNodes.call(this);
        }
    },


    reload: function (callback, scope) {
        this.collapse(false, false);
        while (this.firstChild) {
            this.removeChild(this.firstChild).destroy();
        }
        this.childrenRendered = false;
        this.loaded = false;
        if (this.isHiddenRoot()) {
            this.expanded = false;
        }
        this.expand(false, false, callback, scope);
    }
});

Ext.tree.TreePanel.nodeTypes.async = Ext.tree.AsyncTreeNode;
Ext.tree.TreeNodeUI = Ext.extend(Object, {

    constructor: function (node) {
        Ext.apply(this, {
            node: node,
            rendered: false,
            animating: false,
            wasLeaf: true,
            ecc: 'x-tree-ec-icon x-tree-elbow',
            emptyIcon: Ext.BLANK_IMAGE_URL
        });
    },


    removeChild: function (node) {
        if (this.rendered) {
            this.ctNode.removeChild(node.ui.getEl());
        }
    },


    beforeLoad: function () {
        this.addClass("x-tree-node-loading");
    },


    afterLoad: function () {
        this.removeClass("x-tree-node-loading");
    },


    onTextChange: function (node, text, oldText) {
        if (this.rendered) {
            this.textNode.innerHTML = text;
        }
    },


    onIconClsChange: function (node, cls, oldCls) {
        if (this.rendered) {
            Ext.fly(this.iconNode).replaceClass(oldCls, cls);
        }
    },


    onIconChange: function (node, icon) {
        if (this.rendered) {

            var empty = Ext.isEmpty(icon);
            this.iconNode.src = empty ? this.emptyIcon : icon;
            Ext.fly(this.iconNode)[empty ? 'removeClass' : 'addClass']('x-tree-node-inline-icon');
        }
    },


    onTipChange: function (node, tip, title) {
        if (this.rendered) {
            var hasTitle = Ext.isDefined(title);
            if (this.textNode.setAttributeNS) {
                this.textNode.setAttributeNS("ext", "qtip", tip);
                if (hasTitle) {
                    this.textNode.setAttributeNS("ext", "qtitle", title);
                }
            } else {
                this.textNode.setAttribute("ext:qtip", tip);
                if (hasTitle) {
                    this.textNode.setAttribute("ext:qtitle", title);
                }
            }
        }
    },


    onHrefChange: function (node, href, target) {
        if (this.rendered) {
            this.anchor.href = this.getHref(href);
            if (Ext.isDefined(target)) {
                this.anchor.target = target;
            }
        }
    },


    onClsChange: function (node, cls, oldCls) {
        if (this.rendered) {
            Ext.fly(this.elNode).replaceClass(oldCls, cls);
        }
    },


    onDisableChange: function (node, state) {
        this.disabled = state;
        if (this.checkbox) {
            this.checkbox.disabled = state;
        }
        this[state ? 'addClass' : 'removeClass']('x-tree-node-disabled');
    },


    onSelectedChange: function (state) {
        if (state) {
            this.focus();
            this.addClass("x-tree-selected");
        } else {

            this.removeClass("x-tree-selected");
        }
    },


    onMove: function (tree, node, oldParent, newParent, index, refNode) {
        this.childIndent = null;
        if (this.rendered) {
            var targetNode = newParent.ui.getContainer();
            if (!targetNode) {
                this.holder = document.createElement("div");
                this.holder.appendChild(this.wrap);
                return;
            }
            var insertBefore = refNode ? refNode.ui.getEl() : null;
            if (insertBefore) {
                targetNode.insertBefore(this.wrap, insertBefore);
            } else {
                targetNode.appendChild(this.wrap);
            }
            this.node.renderIndent(true, oldParent != newParent);
        }
    },


    addClass: function (cls) {
        if (this.elNode) {
            Ext.fly(this.elNode).addClass(cls);
        }
    },


    removeClass: function (cls) {
        if (this.elNode) {
            Ext.fly(this.elNode).removeClass(cls);
        }
    },


    remove: function () {
        if (this.rendered) {
            this.holder = document.createElement("div");
            this.holder.appendChild(this.wrap);
        }
    },


    fireEvent: function () {
        return this.node.fireEvent.apply(this.node, arguments);
    },


    initEvents: function () {
        this.node.on("move", this.onMove, this);

        if (this.node.disabled) {
            this.onDisableChange(this.node, true);
        }
        if (this.node.hidden) {
            this.hide();
        }
        var ot = this.node.getOwnerTree();
        var dd = ot.enableDD || ot.enableDrag || ot.enableDrop;
        if (dd && (!this.node.isRoot || ot.rootVisible)) {
            Ext.dd.Registry.register(this.elNode, {
                node: this.node,
                handles: this.getDDHandles(),
                isHandle: false
            });
        }
    },


    getDDHandles: function () {
        return [this.iconNode, this.textNode, this.elNode];
    },


    hide: function () {
        this.node.hidden = true;
        if (this.wrap) {
            this.wrap.style.display = "none";
        }
    },


    show: function () {
        this.node.hidden = false;
        if (this.wrap) {
            this.wrap.style.display = "";
        }
    },


    onContextMenu: function (e) {
        if (this.node.hasListener("contextmenu") || this.node.getOwnerTree().hasListener("contextmenu")) {
            e.preventDefault();
            this.focus();
            this.fireEvent("contextmenu", this.node, e);
        }
    },


    onClick: function (e) {
        if (this.dropping) {
            e.stopEvent();
            return;
        }
        if (this.fireEvent("beforeclick", this.node, e) !== false) {
            var a = e.getTarget('a');
            if (!this.disabled && this.node.attributes.href && a) {
                this.fireEvent("click", this.node, e);
                return;
            } else if (a && e.ctrlKey) {
                e.stopEvent();
            }
            e.preventDefault();
            if (this.disabled) {
                return;
            }

            if (this.node.attributes.singleClickExpand && !this.animating && this.node.isExpandable()) {
                this.node.toggle();
            }

            this.fireEvent("click", this.node, e);
        } else {
            e.stopEvent();
        }
    },


    onDblClick: function (e) {
        e.preventDefault();
        if (this.disabled) {
            return;
        }
        if (this.fireEvent("beforedblclick", this.node, e) !== false) {
            if (this.checkbox) {
                this.toggleCheck();
            }
            if (!this.animating && this.node.isExpandable()) {
                this.node.toggle();
            }
            this.fireEvent("dblclick", this.node, e);
        }
    },

    onOver: function (e) {
        this.addClass('x-tree-node-over');
    },

    onOut: function (e) {
        this.removeClass('x-tree-node-over');
    },


    onCheckChange: function () {
        var checked = this.checkbox.checked;

        this.checkbox.defaultChecked = checked;
        this.node.attributes.checked = checked;
        this.fireEvent('checkchange', this.node, checked);
    },


    ecClick: function (e) {
        if (!this.animating && this.node.isExpandable()) {
            this.node.toggle();
        }
    },


    startDrop: function () {
        this.dropping = true;
    },


    endDrop: function () {
        setTimeout(function () {
            this.dropping = false;
        } .createDelegate(this), 50);
    },


    expand: function () {
        this.updateExpandIcon();
        this.ctNode.style.display = "";
    },


    focus: function () {
        if (!this.node.preventHScroll) {
            try {
                this.anchor.focus();
            } catch (e) { }
        } else {
            try {
                var noscroll = this.node.getOwnerTree().getTreeEl().dom;
                var l = noscroll.scrollLeft;
                this.anchor.focus();
                noscroll.scrollLeft = l;
            } catch (e) { }
        }
    },


    toggleCheck: function (value) {
        var cb = this.checkbox;
        if (cb) {
            cb.checked = (value === undefined ? !cb.checked : value);
            this.onCheckChange();
        }
    },


    blur: function () {
        try {
            this.anchor.blur();
        } catch (e) { }
    },


    animExpand: function (callback) {
        var ct = Ext.get(this.ctNode);
        ct.stopFx();
        if (!this.node.isExpandable()) {
            this.updateExpandIcon();
            this.ctNode.style.display = "";
            Ext.callback(callback);
            return;
        }
        this.animating = true;
        this.updateExpandIcon();

        ct.slideIn('t', {
            callback: function () {
                this.animating = false;
                Ext.callback(callback);
            },
            scope: this,
            duration: this.node.ownerTree.duration || .25
        });
    },


    highlight: function () {
        var tree = this.node.getOwnerTree();
        Ext.fly(this.wrap).highlight(
            tree.hlColor || "C3DAF9",
            { endColor: tree.hlBaseColor }
        );
    },


    collapse: function () {
        this.updateExpandIcon();
        this.ctNode.style.display = "none";
    },


    animCollapse: function (callback) {
        var ct = Ext.get(this.ctNode);
        ct.enableDisplayMode('block');
        ct.stopFx();

        this.animating = true;
        this.updateExpandIcon();

        ct.slideOut('t', {
            callback: function () {
                this.animating = false;
                Ext.callback(callback);
            },
            scope: this,
            duration: this.node.ownerTree.duration || .25
        });
    },


    getContainer: function () {
        return this.ctNode;
    },


    getEl: function () {
        return this.wrap;
    },


    appendDDGhost: function (ghostNode) {
        ghostNode.appendChild(this.elNode.cloneNode(true));
    },


    getDDRepairXY: function () {
        return Ext.lib.Dom.getXY(this.iconNode);
    },


    onRender: function () {
        this.render();
    },


    render: function (bulkRender) {
        var n = this.node, a = n.attributes;
        var targetNode = n.parentNode ?
              n.parentNode.ui.getContainer() : n.ownerTree.innerCt.dom;

        if (!this.rendered) {
            this.rendered = true;

            this.renderElements(n, a, targetNode, bulkRender);

            if (a.qtip) {
                this.onTipChange(n, a.qtip, a.qtipTitle);
            } else if (a.qtipCfg) {
                a.qtipCfg.target = Ext.id(this.textNode);
                Ext.QuickTips.register(a.qtipCfg);
            }
            this.initEvents();
            if (!this.node.expanded) {
                this.updateExpandIcon(true);
            }
        } else {
            if (bulkRender === true) {
                targetNode.appendChild(this.wrap);
            }
        }
    },


    renderElements: function (n, a, targetNode, bulkRender) {

        this.indentMarkup = n.parentNode ? n.parentNode.ui.getChildIndent() : '';

        var cb = Ext.isBoolean(a.checked),
            nel,
            href = this.getHref(a.href),
            buf = ['<li class="x-tree-node"><div ext:tree-node-id="', n.id, '" class="x-tree-node-el x-tree-node-leaf x-unselectable ', a.cls, '" unselectable="on">',
            '<span class="x-tree-node-indent">', this.indentMarkup, "</span>",
            '<img alt="" src="', this.emptyIcon, '" class="x-tree-ec-icon x-tree-elbow" />',
            '<img alt="" src="', a.icon || this.emptyIcon, '" class="x-tree-node-icon', (a.icon ? " x-tree-node-inline-icon" : ""), (a.iconCls ? " " + a.iconCls : ""), '" unselectable="on" />',
            cb ? ('<input class="x-tree-node-cb" type="checkbox" ' + (a.checked ? 'checked="checked" />' : '/>')) : '',
            '<a hidefocus="on" class="x-tree-node-anchor" href="', href, '" tabIndex="1" ',
             a.hrefTarget ? ' target="' + a.hrefTarget + '"' : "", '><span unselectable="on">', n.text, "</span></a></div>",
            '<ul class="x-tree-node-ct" style="display:none;"></ul>',
            "</li>"].join('');

        if (bulkRender !== true && n.nextSibling && (nel = n.nextSibling.ui.getEl())) {
            this.wrap = Ext.DomHelper.insertHtml("beforeBegin", nel, buf);
        } else {
            this.wrap = Ext.DomHelper.insertHtml("beforeEnd", targetNode, buf);
        }

        this.elNode = this.wrap.childNodes[0];
        this.ctNode = this.wrap.childNodes[1];
        var cs = this.elNode.childNodes;
        this.indentNode = cs[0];
        this.ecNode = cs[1];
        this.iconNode = cs[2];
        var index = 3;
        if (cb) {
            this.checkbox = cs[3];

            this.checkbox.defaultChecked = this.checkbox.checked;
            index++;
        }
        this.anchor = cs[index];
        this.textNode = cs[index].firstChild;
    },


    getHref: function (href) {
        return Ext.isEmpty(href) ? (Ext.isGecko ? '' : '#') : href;
    },


    getAnchor: function () {
        return this.anchor;
    },


    getTextEl: function () {
        return this.textNode;
    },


    getIconEl: function () {
        return this.iconNode;
    },


    isChecked: function () {
        return this.checkbox ? this.checkbox.checked : false;
    },


    updateExpandIcon: function () {
        if (this.rendered) {
            var n = this.node,
                c1,
                c2,
                cls = n.isLast() ? "x-tree-elbow-end" : "x-tree-elbow",
                hasChild = n.hasChildNodes();
            if (hasChild || n.attributes.expandable) {
                if (n.expanded) {
                    cls += "-minus";
                    c1 = "x-tree-node-collapsed";
                    c2 = "x-tree-node-expanded";
                } else {
                    cls += "-plus";
                    c1 = "x-tree-node-expanded";
                    c2 = "x-tree-node-collapsed";
                }
                if (this.wasLeaf) {
                    this.removeClass("x-tree-node-leaf");
                    this.wasLeaf = false;
                }
                if (this.c1 != c1 || this.c2 != c2) {
                    Ext.fly(this.elNode).replaceClass(c1, c2);
                    this.c1 = c1; this.c2 = c2;
                }
            } else {
                if (!this.wasLeaf) {
                    Ext.fly(this.elNode).replaceClass("x-tree-node-expanded", "x-tree-node-collapsed");
                    delete this.c1;
                    delete this.c2;
                    this.wasLeaf = true;
                }
            }
            var ecc = "x-tree-ec-icon " + cls;
            if (this.ecc != ecc) {
                this.ecNode.className = ecc;
                this.ecc = ecc;
            }
        }
    },


    onIdChange: function (id) {
        if (this.rendered) {
            this.elNode.setAttribute('ext:tree-node-id', id);
        }
    },


    getChildIndent: function () {
        if (!this.childIndent) {
            var buf = [],
                p = this.node;
            while (p) {
                if (!p.isRoot || (p.isRoot && p.ownerTree.rootVisible)) {
                    if (!p.isLast()) {
                        buf.unshift('<img alt="" src="' + this.emptyIcon + '" class="x-tree-elbow-line" />');
                    } else {
                        buf.unshift('<img alt="" src="' + this.emptyIcon + '" class="x-tree-icon" />');
                    }
                }
                p = p.parentNode;
            }
            this.childIndent = buf.join("");
        }
        return this.childIndent;
    },


    renderIndent: function () {
        if (this.rendered) {
            var indent = "",
                p = this.node.parentNode;
            if (p) {
                indent = p.ui.getChildIndent();
            }
            if (this.indentMarkup != indent) {
                this.indentNode.innerHTML = indent;
                this.indentMarkup = indent;
            }
            this.updateExpandIcon();
        }
    },

    destroy: function () {
        if (this.elNode) {
            Ext.dd.Registry.unregister(this.elNode.id);
        }

        Ext.each(['textnode', 'anchor', 'checkbox', 'indentNode', 'ecNode', 'iconNode', 'elNode', 'ctNode', 'wrap', 'holder'], function (el) {
            if (this[el]) {
                Ext.fly(this[el]).remove();
                delete this[el];
            }
        }, this);
        delete this.node;
    }
});


Ext.tree.RootTreeNodeUI = Ext.extend(Ext.tree.TreeNodeUI, {

    render: function () {
        if (!this.rendered) {
            var targetNode = this.node.ownerTree.innerCt.dom;
            this.node.expanded = true;
            targetNode.innerHTML = '<div class="x-tree-root-node"></div>';
            this.wrap = this.ctNode = targetNode.firstChild;
        }
    },
    collapse: Ext.emptyFn,
    expand: Ext.emptyFn
});
Ext.tree.TreeLoader = function (config) {
    this.baseParams = {};
    Ext.apply(this, config);

    this.addEvents(

        "beforeload",

        "load",

        "loadexception"
    );
    Ext.tree.TreeLoader.superclass.constructor.call(this);
    if (Ext.isString(this.paramOrder)) {
        this.paramOrder = this.paramOrder.split(/[\s,|]/);
    }
};

Ext.extend(Ext.tree.TreeLoader, Ext.util.Observable, {







    uiProviders: {},


    clearOnLoad: true,


    paramOrder: undefined,


    paramsAsHash: false,


    nodeParameter: 'node',


    directFn: undefined,


    load: function (node, callback, scope) {
        if (this.clearOnLoad) {
            while (node.firstChild) {
                node.removeChild(node.firstChild);
            }
        }
        if (this.doPreload(node)) {
            this.runCallback(callback, scope || node, [node]);
        } else if (this.directFn || this.dataUrl || this.url) {
            this.requestData(node, callback, scope || node);
        }
    },

    doPreload: function (node) {
        if (node.attributes.children) {
            if (node.childNodes.length < 1) {
                var cs = node.attributes.children;
                node.beginUpdate();
                for (var i = 0, len = cs.length; i < len; i++) {
                    var cn = node.appendChild(this.createNode(cs[i]));
                    if (this.preloadChildren) {
                        this.doPreload(cn);
                    }
                }
                node.endUpdate();
            }
            return true;
        }
        return false;
    },

    getParams: function (node) {
        var bp = Ext.apply({}, this.baseParams),
            np = this.nodeParameter,
            po = this.paramOrder;

        np && (bp[np] = node.id);

        if (this.directFn) {
            var buf = [node.id];
            if (po) {

                if (np && po.indexOf(np) > -1) {
                    buf = [];
                }

                for (var i = 0, len = po.length; i < len; i++) {
                    buf.push(bp[po[i]]);
                }
            } else if (this.paramsAsHash) {
                buf = [bp];
            }
            return buf;
        } else {
            return bp;
        }
    },

    requestData: function (node, callback, scope) {
        if (this.fireEvent("beforeload", this, node, callback) !== false) {
            if (this.directFn) {
                var args = this.getParams(node);
                args.push(this.processDirectResponse.createDelegate(this, [{ callback: callback, node: node, scope: scope}], true));
                this.directFn.apply(window, args);
            } else {
                this.transId = Ext.Ajax.request({
                    method: this.requestMethod,
                    url: this.dataUrl || this.url,
                    success: this.handleResponse,
                    failure: this.handleFailure,
                    scope: this,
                    argument: { callback: callback, node: node, scope: scope },
                    params: this.getParams(node)
                });
            }
        } else {


            this.runCallback(callback, scope || node, []);
        }
    },

    processDirectResponse: function (result, response, args) {
        if (response.status) {
            this.handleResponse({
                responseData: Ext.isArray(result) ? result : null,
                responseText: result,
                argument: args
            });
        } else {
            this.handleFailure({
                argument: args
            });
        }
    },


    runCallback: function (cb, scope, args) {
        if (Ext.isFunction(cb)) {
            cb.apply(scope, args);
        }
    },

    isLoading: function () {
        return !!this.transId;
    },

    abort: function () {
        if (this.isLoading()) {
            Ext.Ajax.abort(this.transId);
        }
    },


    createNode: function (attr) {

        if (this.baseAttrs) {
            Ext.applyIf(attr, this.baseAttrs);
        }
        if (this.applyLoader !== false && !attr.loader) {
            attr.loader = this;
        }
        if (Ext.isString(attr.uiProvider)) {
            attr.uiProvider = this.uiProviders[attr.uiProvider] || eval(attr.uiProvider);
        }
        if (attr.nodeType) {
            return new Ext.tree.TreePanel.nodeTypes[attr.nodeType](attr);
        } else {
            return attr.leaf ?
                        new Ext.tree.TreeNode(attr) :
                        new Ext.tree.AsyncTreeNode(attr);
        }
    },

    processResponse: function (response, node, callback, scope) {
        var json = response.responseText;
        try {
            var o = response.responseData || Ext.decode(json);
            node.beginUpdate();
            for (var i = 0, len = o.length; i < len; i++) {
                var n = this.createNode(o[i]);
                if (n) {
                    node.appendChild(n);
                }
            }
            node.endUpdate();
            this.runCallback(callback, scope || node, [node]);
        } catch (e) {
            this.handleFailure(response);
        }
    },

    handleResponse: function (response) {
        this.transId = false;
        var a = response.argument;
        this.processResponse(response, a.node, a.callback, a.scope);
        this.fireEvent("load", this, a.node, response);
    },

    handleFailure: function (response) {
        this.transId = false;
        var a = response.argument;
        this.fireEvent("loadexception", this, a.node, response);
        this.runCallback(a.callback, a.scope || a.node, [a.node]);
    },

    destroy: function () {
        this.abort();
        this.purgeListeners();
    }
});
Ext.tree.TreeFilter = function (tree, config) {
    this.tree = tree;
    this.filtered = {};
    Ext.apply(this, config);
};

Ext.tree.TreeFilter.prototype = {
    clearBlank: false,
    reverse: false,
    autoClear: false,
    remove: false,


    filter: function (value, attr, startNode) {
        attr = attr || "text";
        var f;
        if (typeof value == "string") {
            var vlen = value.length;

            if (vlen == 0 && this.clearBlank) {
                this.clear();
                return;
            }
            value = value.toLowerCase();
            f = function (n) {
                return n.attributes[attr].substr(0, vlen).toLowerCase() == value;
            };
        } else if (value.exec) {
            f = function (n) {
                return value.test(n.attributes[attr]);
            };
        } else {
            throw 'Illegal filter type, must be string or regex';
        }
        this.filterBy(f, null, startNode);
    },


    filterBy: function (fn, scope, startNode) {
        startNode = startNode || this.tree.root;
        if (this.autoClear) {
            this.clear();
        }
        var af = this.filtered, rv = this.reverse;
        var f = function (n) {
            if (n == startNode) {
                return true;
            }
            if (af[n.id]) {
                return false;
            }
            var m = fn.call(scope || n, n);
            if (!m || rv) {
                af[n.id] = n;
                n.ui.hide();
                return false;
            }
            return true;
        };
        startNode.cascade(f);
        if (this.remove) {
            for (var id in af) {
                if (typeof id != "function") {
                    var n = af[id];
                    if (n && n.parentNode) {
                        n.parentNode.removeChild(n);
                    }
                }
            }
        }
    },


    clear: function () {
        var t = this.tree;
        var af = this.filtered;
        for (var id in af) {
            if (typeof id != "function") {
                var n = af[id];
                if (n) {
                    n.ui.show();
                }
            }
        }
        this.filtered = {};
    }
};

Ext.tree.TreeSorter = Ext.extend(Object, {

    constructor: function (tree, config) {







        Ext.apply(this, config);
        tree.on({
            scope: this,
            beforechildrenrendered: this.doSort,
            append: this.updateSort,
            insert: this.updateSort,
            textchange: this.updateSortParent
        });

        var desc = this.dir && this.dir.toLowerCase() == 'desc',
        prop = this.property || 'text';
        sortType = this.sortType;
        folderSort = this.folderSort;
        caseSensitive = this.caseSensitive === true;
        leafAttr = this.leafAttr || 'leaf';

        if (Ext.isString(sortType)) {
            sortType = Ext.data.SortTypes[sortType];
        }
        this.sortFn = function (n1, n2) {
            var attr1 = n1.attributes,
            attr2 = n2.attributes;

            if (folderSort) {
                if (attr1[leafAttr] && !attr2[leafAttr]) {
                    return 1;
                }
                if (!attr1[leafAttr] && attr2[leafAttr]) {
                    return -1;
                }
            }
            var prop1 = attr1[prop],
            prop2 = attr2[prop],
            v1 = sortType ? sortType(prop1) : (caseSensitive ? prop1 : prop1.toUpperCase());
            v2 = sortType ? sortType(prop2) : (caseSensitive ? prop2 : prop2.toUpperCase());

            if (v1 < v2) {
                return desc ? 1 : -1;
            } else if (v1 > v2) {
                return desc ? -1 : 1;
            }
            return 0;
        };
    },

    doSort: function (node) {
        node.sort(this.sortFn);
    },

    updateSort: function (tree, node) {
        if (node.childrenRendered) {
            this.doSort.defer(1, this, [node]);
        }
    },

    updateSortParent: function (node) {
        var p = node.parentNode;
        if (p && p.childrenRendered) {
            this.doSort.defer(1, this, [p]);
        }
    }
});
if (Ext.dd.DropZone) {

    Ext.tree.TreeDropZone = function (tree, config) {

        this.allowParentInsert = config.allowParentInsert || false;

        this.allowContainerDrop = config.allowContainerDrop || false;

        this.appendOnly = config.appendOnly || false;

        Ext.tree.TreeDropZone.superclass.constructor.call(this, tree.getTreeEl(), config);

        this.tree = tree;

        this.dragOverData = {};

        this.lastInsertClass = "x-tree-no-status";
    };

    Ext.extend(Ext.tree.TreeDropZone, Ext.dd.DropZone, {

        ddGroup: "TreeDD",


        expandDelay: 1000,


        expandNode: function (node) {
            if (node.hasChildNodes() && !node.isExpanded()) {
                node.expand(false, null, this.triggerCacheRefresh.createDelegate(this));
            }
        },


        queueExpand: function (node) {
            this.expandProcId = this.expandNode.defer(this.expandDelay, this, [node]);
        },


        cancelExpand: function () {
            if (this.expandProcId) {
                clearTimeout(this.expandProcId);
                this.expandProcId = false;
            }
        },


        isValidDropPoint: function (n, pt, dd, e, data) {
            if (!n || !data) { return false; }
            var targetNode = n.node;
            var dropNode = data.node;

            if (!(targetNode && targetNode.isTarget && pt)) {
                return false;
            }
            if (pt == "append" && targetNode.allowChildren === false) {
                return false;
            }
            if ((pt == "above" || pt == "below") && (targetNode.parentNode && targetNode.parentNode.allowChildren === false)) {
                return false;
            }
            if (dropNode && (targetNode == dropNode || dropNode.contains(targetNode))) {
                return false;
            }

            var overEvent = this.dragOverData;
            overEvent.tree = this.tree;
            overEvent.target = targetNode;
            overEvent.data = data;
            overEvent.point = pt;
            overEvent.source = dd;
            overEvent.rawEvent = e;
            overEvent.dropNode = dropNode;
            overEvent.cancel = false;
            var result = this.tree.fireEvent("nodedragover", overEvent);
            return overEvent.cancel === false && result !== false;
        },


        getDropPoint: function (e, n, dd) {
            var tn = n.node;
            if (tn.isRoot) {
                return tn.allowChildren !== false ? "append" : false;
            }
            var dragEl = n.ddel;
            var t = Ext.lib.Dom.getY(dragEl), b = t + dragEl.offsetHeight;
            var y = Ext.lib.Event.getPageY(e);
            var noAppend = tn.allowChildren === false || tn.isLeaf();
            if (this.appendOnly || tn.parentNode.allowChildren === false) {
                return noAppend ? false : "append";
            }
            var noBelow = false;
            if (!this.allowParentInsert) {
                noBelow = tn.hasChildNodes() && tn.isExpanded();
            }
            var q = (b - t) / (noAppend ? 2 : 3);
            if (y >= t && y < (t + q)) {
                return "above";
            } else if (!noBelow && (noAppend || y >= b - q && y <= b)) {
                return "below";
            } else {
                return "append";
            }
        },


        onNodeEnter: function (n, dd, e, data) {
            this.cancelExpand();
        },

        onContainerOver: function (dd, e, data) {
            if (this.allowContainerDrop && this.isValidDropPoint({ ddel: this.tree.getRootNode().ui.elNode, node: this.tree.getRootNode() }, "append", dd, e, data)) {
                return this.dropAllowed;
            }
            return this.dropNotAllowed;
        },


        onNodeOver: function (n, dd, e, data) {
            var pt = this.getDropPoint(e, n, dd);
            var node = n.node;


            if (!this.expandProcId && pt == "append" && node.hasChildNodes() && !n.node.isExpanded()) {
                this.queueExpand(node);
            } else if (pt != "append") {
                this.cancelExpand();
            }


            var returnCls = this.dropNotAllowed;
            if (this.isValidDropPoint(n, pt, dd, e, data)) {
                if (pt) {
                    var el = n.ddel;
                    var cls;
                    if (pt == "above") {
                        returnCls = n.node.isFirst() ? "x-tree-drop-ok-above" : "x-tree-drop-ok-between";
                        cls = "x-tree-drag-insert-above";
                    } else if (pt == "below") {
                        returnCls = n.node.isLast() ? "x-tree-drop-ok-below" : "x-tree-drop-ok-between";
                        cls = "x-tree-drag-insert-below";
                    } else {
                        returnCls = "x-tree-drop-ok-append";
                        cls = "x-tree-drag-append";
                    }
                    if (this.lastInsertClass != cls) {
                        Ext.fly(el).replaceClass(this.lastInsertClass, cls);
                        this.lastInsertClass = cls;
                    }
                }
            }
            return returnCls;
        },


        onNodeOut: function (n, dd, e, data) {
            this.cancelExpand();
            this.removeDropIndicators(n);
        },


        onNodeDrop: function (n, dd, e, data) {
            var point = this.getDropPoint(e, n, dd);
            var targetNode = n.node;
            targetNode.ui.startDrop();
            if (!this.isValidDropPoint(n, point, dd, e, data)) {
                targetNode.ui.endDrop();
                return false;
            }

            var dropNode = data.node || (dd.getTreeNode ? dd.getTreeNode(data, targetNode, point, e) : null);
            return this.processDrop(targetNode, data, point, dd, e, dropNode);
        },

        onContainerDrop: function (dd, e, data) {
            if (this.allowContainerDrop && this.isValidDropPoint({ ddel: this.tree.getRootNode().ui.elNode, node: this.tree.getRootNode() }, "append", dd, e, data)) {
                var targetNode = this.tree.getRootNode();
                targetNode.ui.startDrop();
                var dropNode = data.node || (dd.getTreeNode ? dd.getTreeNode(data, targetNode, 'append', e) : null);
                return this.processDrop(targetNode, data, 'append', dd, e, dropNode);
            }
            return false;
        },


        processDrop: function (target, data, point, dd, e, dropNode) {
            var dropEvent = {
                tree: this.tree,
                target: target,
                data: data,
                point: point,
                source: dd,
                rawEvent: e,
                dropNode: dropNode,
                cancel: !dropNode,
                dropStatus: false
            };
            var retval = this.tree.fireEvent("beforenodedrop", dropEvent);
            if (retval === false || dropEvent.cancel === true || !dropEvent.dropNode) {
                target.ui.endDrop();
                return dropEvent.dropStatus;
            }

            target = dropEvent.target;
            if (point == 'append' && !target.isExpanded()) {
                target.expand(false, null, function () {
                    this.completeDrop(dropEvent);
                } .createDelegate(this));
            } else {
                this.completeDrop(dropEvent);
            }
            return true;
        },


        completeDrop: function (de) {
            var ns = de.dropNode, p = de.point, t = de.target;
            if (!Ext.isArray(ns)) {
                ns = [ns];
            }
            var n;
            for (var i = 0, len = ns.length; i < len; i++) {
                n = ns[i];
                if (p == "above") {
                    t.parentNode.insertBefore(n, t);
                } else if (p == "below") {
                    t.parentNode.insertBefore(n, t.nextSibling);
                } else {
                    t.appendChild(n);
                }
            }
            n.ui.focus();
            if (Ext.enableFx && this.tree.hlDrop) {
                n.ui.highlight();
            }
            t.ui.endDrop();
            this.tree.fireEvent("nodedrop", de);
        },


        afterNodeMoved: function (dd, data, e, targetNode, dropNode) {
            if (Ext.enableFx && this.tree.hlDrop) {
                dropNode.ui.focus();
                dropNode.ui.highlight();
            }
            this.tree.fireEvent("nodedrop", this.tree, targetNode, data, dd, e);
        },


        getTree: function () {
            return this.tree;
        },


        removeDropIndicators: function (n) {
            if (n && n.ddel) {
                var el = n.ddel;
                Ext.fly(el).removeClass([
                    "x-tree-drag-insert-above",
                    "x-tree-drag-insert-below",
                    "x-tree-drag-append"]);
                this.lastInsertClass = "_noclass";
            }
        },


        beforeDragDrop: function (target, e, id) {
            this.cancelExpand();
            return true;
        },


        afterRepair: function (data) {
            if (data && Ext.enableFx) {
                data.node.ui.highlight();
            }
            this.hideProxy();
        }
    });

}
if (Ext.dd.DragZone) {
    Ext.tree.TreeDragZone = function (tree, config) {
        Ext.tree.TreeDragZone.superclass.constructor.call(this, tree.innerCt, config);

        this.tree = tree;
    };

    Ext.extend(Ext.tree.TreeDragZone, Ext.dd.DragZone, {

        ddGroup: "TreeDD",


        onBeforeDrag: function (data, e) {
            var n = data.node;
            return n && n.draggable && !n.disabled;
        },


        onInitDrag: function (e) {
            var data = this.dragData;
            this.tree.getSelectionModel().select(data.node);
            this.tree.eventModel.disable();
            this.proxy.update("");
            data.node.ui.appendDDGhost(this.proxy.ghost.dom);
            this.tree.fireEvent("startdrag", this.tree, data.node, e);
        },


        getRepairXY: function (e, data) {
            return data.node.ui.getDDRepairXY();
        },


        onEndDrag: function (data, e) {
            this.tree.eventModel.enable.defer(100, this.tree.eventModel);
            this.tree.fireEvent("enddrag", this.tree, data.node, e);
        },


        onValidDrop: function (dd, e, id) {
            this.tree.fireEvent("dragdrop", this.tree, this.dragData.node, dd, e);
            this.hideProxy();
        },


        beforeInvalidDrop: function (e, id) {

            var sm = this.tree.getSelectionModel();
            sm.clearSelections();
            sm.select(this.dragData.node);
        },


        afterRepair: function () {
            if (Ext.enableFx && this.tree.hlDrop) {
                Ext.Element.fly(this.dragData.ddel).highlight(this.hlColor || "c3daf9");
            }
            this.dragging = false;
        }
    });
}
Ext.tree.TreeEditor = function (tree, fc, config) {
    fc = fc || {};
    var field = fc.events ? fc : new Ext.form.TextField(fc);

    Ext.tree.TreeEditor.superclass.constructor.call(this, field, config);

    this.tree = tree;

    if (!tree.rendered) {
        tree.on('render', this.initEditor, this);
    } else {
        this.initEditor(tree);
    }
};

Ext.extend(Ext.tree.TreeEditor, Ext.Editor, {

    alignment: "l-l",

    autoSize: false,

    hideEl: false,

    cls: "x-small-editor x-tree-editor",

    shim: false,

    shadow: "frame",

    maxWidth: 250,

    editDelay: 350,

    initEditor: function (tree) {
        tree.on({
            scope: this,
            beforeclick: this.beforeNodeClick,
            dblclick: this.onNodeDblClick
        });

        this.on({
            scope: this,
            complete: this.updateNode,
            beforestartedit: this.fitToTree,
            specialkey: this.onSpecialKey
        });

        this.on('startedit', this.bindScroll, this, { delay: 10 });
    },


    fitToTree: function (ed, el) {
        var td = this.tree.getTreeEl().dom, nd = el.dom;
        if (td.scrollLeft > nd.offsetLeft) {
            td.scrollLeft = nd.offsetLeft;
        }
        var w = Math.min(
                this.maxWidth,
                (td.clientWidth > 20 ? td.clientWidth : td.offsetWidth) - Math.max(0, nd.offsetLeft - td.scrollLeft) - 5);
        this.setSize(w, '');
    },


    triggerEdit: function (node, defer) {
        this.completeEdit();
        if (node.attributes.editable !== false) {

            this.editNode = node;
            if (this.tree.autoScroll) {
                Ext.fly(node.ui.getEl()).scrollIntoView(this.tree.body);
            }
            var value = node.text || '';
            if (!Ext.isGecko && Ext.isEmpty(node.text)) {
                node.setText('&#160;');
            }
            this.autoEditTimer = this.startEdit.defer(this.editDelay, this, [node.ui.textNode, value]);
            return false;
        }
    },


    bindScroll: function () {
        this.tree.getTreeEl().on('scroll', this.cancelEdit, this);
    },


    beforeNodeClick: function (node, e) {
        clearTimeout(this.autoEditTimer);
        if (this.tree.getSelectionModel().isSelected(node)) {
            e.stopEvent();
            return this.triggerEdit(node);
        }
    },

    onNodeDblClick: function (node, e) {
        clearTimeout(this.autoEditTimer);
    },


    updateNode: function (ed, value) {
        this.tree.getTreeEl().un('scroll', this.cancelEdit, this);
        this.editNode.setText(value);
    },


    onHide: function () {
        Ext.tree.TreeEditor.superclass.onHide.call(this);
        if (this.editNode) {
            this.editNode.ui.focus.defer(50, this.editNode.ui);
        }
    },


    onSpecialKey: function (field, e) {
        var k = e.getKey();
        if (k == e.ESC) {
            e.stopEvent();
            this.cancelEdit();
        } else if (k == e.ENTER && !e.hasModifier()) {
            e.stopEvent();
            this.completeEdit();
        }
    },

    onDestroy: function () {
        clearTimeout(this.autoEditTimer);
        Ext.tree.TreeEditor.superclass.onDestroy.call(this);
        var tree = this.tree;
        tree.un('beforeclick', this.beforeNodeClick, this);
        tree.un('dblclick', this.onNodeDblClick, this);
    }
});

var swfobject = function () {

    var UNDEF = "undefined",
        OBJECT = "object",
        SHOCKWAVE_FLASH = "Shockwave Flash",
        SHOCKWAVE_FLASH_AX = "ShockwaveFlash.ShockwaveFlash",
        FLASH_MIME_TYPE = "application/x-shockwave-flash",
        EXPRESS_INSTALL_ID = "SWFObjectExprInst",
        ON_READY_STATE_CHANGE = "onreadystatechange",

        win = window,
        doc = document,
        nav = navigator,

        plugin = false,
        domLoadFnArr = [main],
        regObjArr = [],
        objIdArr = [],
        listenersArr = [],
        storedAltContent,
        storedAltContentId,
        storedCallbackFn,
        storedCallbackObj,
        isDomLoaded = false,
        isExpressInstallActive = false,
        dynamicStylesheet,
        dynamicStylesheetMedia,
        autoHideShow = true,


    ua = function () {
        var w3cdom = typeof doc.getElementById != UNDEF && typeof doc.getElementsByTagName != UNDEF && typeof doc.createElement != UNDEF,
            u = nav.userAgent.toLowerCase(),
            p = nav.platform.toLowerCase(),
            windows = p ? (/win/).test(p) : /win/.test(u),
            mac = p ? (/mac/).test(p) : /mac/.test(u),
            webkit = /webkit/.test(u) ? parseFloat(u.replace(/^.*webkit\/(\d+(\.\d+)?).*$/, "$1")) : false,
            ie = ! +"\v1",
            playerVersion = [0, 0, 0],
            d = null;
        if (typeof nav.plugins != UNDEF && typeof nav.plugins[SHOCKWAVE_FLASH] == OBJECT) {
            d = nav.plugins[SHOCKWAVE_FLASH].description;
            if (d && !(typeof nav.mimeTypes != UNDEF && nav.mimeTypes[FLASH_MIME_TYPE] && !nav.mimeTypes[FLASH_MIME_TYPE].enabledPlugin)) {
                plugin = true;
                ie = false;
                d = d.replace(/^.*\s+(\S+\s+\S+$)/, "$1");
                playerVersion[0] = parseInt(d.replace(/^(.*)\..*$/, "$1"), 10);
                playerVersion[1] = parseInt(d.replace(/^.*\.(.*)\s.*$/, "$1"), 10);
                playerVersion[2] = /[a-zA-Z]/.test(d) ? parseInt(d.replace(/^.*[a-zA-Z]+(.*)$/, "$1"), 10) : 0;
            }
        }
        else if (typeof win.ActiveXObject != UNDEF) {
            try {
                var a = new ActiveXObject(SHOCKWAVE_FLASH_AX);
                if (a) {
                    d = a.GetVariable("$version");
                    if (d) {
                        ie = true;
                        d = d.split(" ")[1].split(",");
                        playerVersion = [parseInt(d[0], 10), parseInt(d[1], 10), parseInt(d[2], 10)];
                    }
                }
            }
            catch (e) { }
        }
        return { w3: w3cdom, pv: playerVersion, wk: webkit, ie: ie, win: windows, mac: mac };
    } (),


    onDomLoad = function () {
        if (!ua.w3) { return; }
        if ((typeof doc.readyState != UNDEF && doc.readyState == "complete") || (typeof doc.readyState == UNDEF && (doc.getElementsByTagName("body")[0] || doc.body))) {
            callDomLoadFunctions();
        }
        if (!isDomLoaded) {
            if (typeof doc.addEventListener != UNDEF) {
                doc.addEventListener("DOMContentLoaded", callDomLoadFunctions, false);
            }
            if (ua.ie && ua.win) {
                doc.attachEvent(ON_READY_STATE_CHANGE, function () {
                    if (doc.readyState == "complete") {
                        doc.detachEvent(ON_READY_STATE_CHANGE, arguments.callee);
                        callDomLoadFunctions();
                    }
                });
                if (win == top) {
                    (function () {
                        if (isDomLoaded) { return; }
                        try {
                            doc.documentElement.doScroll("left");
                        }
                        catch (e) {
                            setTimeout(arguments.callee, 0);
                            return;
                        }
                        callDomLoadFunctions();
                    })();
                }
            }
            if (ua.wk) {
                (function () {
                    if (isDomLoaded) { return; }
                    if (!(/loaded|complete/).test(doc.readyState)) {
                        setTimeout(arguments.callee, 0);
                        return;
                    }
                    callDomLoadFunctions();
                })();
            }
            addLoadEvent(callDomLoadFunctions);
        }
    } ();

    function callDomLoadFunctions() {
        if (isDomLoaded) { return; }
        try {
            var t = doc.getElementsByTagName("body")[0].appendChild(createElement("span"));
            t.parentNode.removeChild(t);
        }
        catch (e) { return; }
        isDomLoaded = true;
        var dl = domLoadFnArr.length;
        for (var i = 0; i < dl; i++) {
            domLoadFnArr[i]();
        }
    }

    function addDomLoadEvent(fn) {
        if (isDomLoaded) {
            fn();
        }
        else {
            domLoadFnArr[domLoadFnArr.length] = fn;
        }
    }


    function addLoadEvent(fn) {
        if (typeof win.addEventListener != UNDEF) {
            win.addEventListener("load", fn, false);
        }
        else if (typeof doc.addEventListener != UNDEF) {
            doc.addEventListener("load", fn, false);
        }
        else if (typeof win.attachEvent != UNDEF) {
            addListener(win, "onload", fn);
        }
        else if (typeof win.onload == "function") {
            var fnOld = win.onload;
            win.onload = function () {
                fnOld();
                fn();
            };
        }
        else {
            win.onload = fn;
        }
    }


    function main() {
        if (plugin) {
            testPlayerVersion();
        }
        else {
            matchVersions();
        }
    }


    function testPlayerVersion() {
        var b = doc.getElementsByTagName("body")[0];
        var o = createElement(OBJECT);
        o.setAttribute("type", FLASH_MIME_TYPE);
        var t = b.appendChild(o);
        if (t) {
            var counter = 0;
            (function () {
                if (typeof t.GetVariable != UNDEF) {
                    var d = t.GetVariable("$version");
                    if (d) {
                        d = d.split(" ")[1].split(",");
                        ua.pv = [parseInt(d[0], 10), parseInt(d[1], 10), parseInt(d[2], 10)];
                    }
                }
                else if (counter < 10) {
                    counter++;
                    setTimeout(arguments.callee, 10);
                    return;
                }
                b.removeChild(o);
                t = null;
                matchVersions();
            })();
        }
        else {
            matchVersions();
        }
    }


    function matchVersions() {
        var rl = regObjArr.length;
        if (rl > 0) {
            for (var i = 0; i < rl; i++) {
                var id = regObjArr[i].id;
                var cb = regObjArr[i].callbackFn;
                var cbObj = { success: false, id: id };
                if (ua.pv[0] > 0) {
                    var obj = getElementById(id);
                    if (obj) {
                        if (hasPlayerVersion(regObjArr[i].swfVersion) && !(ua.wk && ua.wk < 312)) {
                            setVisibility(id, true);
                            if (cb) {
                                cbObj.success = true;
                                cbObj.ref = getObjectById(id);
                                cb(cbObj);
                            }
                        }
                        else if (regObjArr[i].expressInstall && canExpressInstall()) {
                            var att = {};
                            att.data = regObjArr[i].expressInstall;
                            att.width = obj.getAttribute("width") || "0";
                            att.height = obj.getAttribute("height") || "0";
                            if (obj.getAttribute("class")) { att.styleclass = obj.getAttribute("class"); }
                            if (obj.getAttribute("align")) { att.align = obj.getAttribute("align"); }

                            var par = {};
                            var p = obj.getElementsByTagName("param");
                            var pl = p.length;
                            for (var j = 0; j < pl; j++) {
                                if (p[j].getAttribute("name").toLowerCase() != "movie") {
                                    par[p[j].getAttribute("name")] = p[j].getAttribute("value");
                                }
                            }
                            showExpressInstall(att, par, id, cb);
                        }
                        else {
                            displayAltContent(obj);
                            if (cb) { cb(cbObj); }
                        }
                    }
                }
                else {
                    setVisibility(id, true);
                    if (cb) {
                        var o = getObjectById(id);
                        if (o && typeof o.SetVariable != UNDEF) {
                            cbObj.success = true;
                            cbObj.ref = o;
                        }
                        cb(cbObj);
                    }
                }
            }
        }
    }

    function getObjectById(objectIdStr) {
        var r = null;
        var o = getElementById(objectIdStr);
        if (o && o.nodeName == "OBJECT") {
            if (typeof o.SetVariable != UNDEF) {
                r = o;
            }
            else {
                var n = o.getElementsByTagName(OBJECT)[0];
                if (n) {
                    r = n;
                }
            }
        }
        return r;
    }


    function canExpressInstall() {
        return !isExpressInstallActive && hasPlayerVersion("6.0.65") && (ua.win || ua.mac) && !(ua.wk && ua.wk < 312);
    }


    function showExpressInstall(att, par, replaceElemIdStr, callbackFn) {
        isExpressInstallActive = true;
        storedCallbackFn = callbackFn || null;
        storedCallbackObj = { success: false, id: replaceElemIdStr };
        var obj = getElementById(replaceElemIdStr);
        if (obj) {
            if (obj.nodeName == "OBJECT") {
                storedAltContent = abstractAltContent(obj);
                storedAltContentId = null;
            }
            else {
                storedAltContent = obj;
                storedAltContentId = replaceElemIdStr;
            }
            att.id = EXPRESS_INSTALL_ID;
            if (typeof att.width == UNDEF || (!(/%$/).test(att.width) && parseInt(att.width, 10) < 310)) {
                att.width = "310";
            }

            if (typeof att.height == UNDEF || (!(/%$/).test(att.height) && parseInt(att.height, 10) < 137)) {
                att.height = "137";
            }
            doc.title = doc.title.slice(0, 47) + " - Flash Player Installation";
            var pt = ua.ie && ua.win ? "ActiveX" : "PlugIn",
                fv = "MMredirectURL=" + win.location.toString().replace(/&/g, "%26") + "&MMplayerType=" + pt + "&MMdoctitle=" + doc.title;
            if (typeof par.flashvars != UNDEF) {
                par.flashvars += "&" + fv;
            }
            else {
                par.flashvars = fv;
            }


            if (ua.ie && ua.win && obj.readyState != 4) {
                var newObj = createElement("div");
                replaceElemIdStr += "SWFObjectNew";
                newObj.setAttribute("id", replaceElemIdStr);
                obj.parentNode.insertBefore(newObj, obj);
                obj.style.display = "none";
                (function () {
                    if (obj.readyState == 4) {
                        obj.parentNode.removeChild(obj);
                    }
                    else {
                        setTimeout(arguments.callee, 10);
                    }
                })();
            }
            createSWF(att, par, replaceElemIdStr);
        }
    }


    function displayAltContent(obj) {
        if (ua.ie && ua.win && obj.readyState != 4) {


            var el = createElement("div");
            obj.parentNode.insertBefore(el, obj);
            el.parentNode.replaceChild(abstractAltContent(obj), el);
            obj.style.display = "none";
            (function () {
                if (obj.readyState == 4) {
                    obj.parentNode.removeChild(obj);
                }
                else {
                    setTimeout(arguments.callee, 10);
                }
            })();
        }
        else {
            obj.parentNode.replaceChild(abstractAltContent(obj), obj);
        }
    }

    function abstractAltContent(obj) {
        var ac = createElement("div");
        if (ua.win && ua.ie) {
            ac.innerHTML = obj.innerHTML;
        }
        else {
            var nestedObj = obj.getElementsByTagName(OBJECT)[0];
            if (nestedObj) {
                var c = nestedObj.childNodes;
                if (c) {
                    var cl = c.length;
                    for (var i = 0; i < cl; i++) {
                        if (!(c[i].nodeType == 1 && c[i].nodeName == "PARAM") && !(c[i].nodeType == 8)) {
                            ac.appendChild(c[i].cloneNode(true));
                        }
                    }
                }
            }
        }
        return ac;
    }


    function createSWF(attObj, parObj, id) {
        var r, el = getElementById(id);
        if (ua.wk && ua.wk < 312) { return r; }
        if (el) {
            if (typeof attObj.id == UNDEF) {
                attObj.id = id;
            }
            if (ua.ie && ua.win) {
                var att = "";
                for (var i in attObj) {
                    if (attObj[i] != Object.prototype[i]) {
                        if (i.toLowerCase() == "data") {
                            parObj.movie = attObj[i];
                        }
                        else if (i.toLowerCase() == "styleclass") {
                            att += ' class="' + attObj[i] + '"';
                        }
                        else if (i.toLowerCase() != "classid") {
                            att += ' ' + i + '="' + attObj[i] + '"';
                        }
                    }
                }
                var par = "";
                for (var j in parObj) {
                    if (parObj[j] != Object.prototype[j]) {
                        par += '<param name="' + j + '" value="' + parObj[j] + '" />';
                    }
                }
                el.outerHTML = '<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"' + att + '>' + par + '</object>';
                objIdArr[objIdArr.length] = attObj.id;
                r = getElementById(attObj.id);
            }
            else {
                var o = createElement(OBJECT);
                o.setAttribute("type", FLASH_MIME_TYPE);
                for (var m in attObj) {
                    if (attObj[m] != Object.prototype[m]) {
                        if (m.toLowerCase() == "styleclass") {
                            o.setAttribute("class", attObj[m]);
                        }
                        else if (m.toLowerCase() != "classid") {
                            o.setAttribute(m, attObj[m]);
                        }
                    }
                }
                for (var n in parObj) {
                    if (parObj[n] != Object.prototype[n] && n.toLowerCase() != "movie") {
                        createObjParam(o, n, parObj[n]);
                    }
                }
                el.parentNode.replaceChild(o, el);
                r = o;
            }
        }
        return r;
    }

    function createObjParam(el, pName, pValue) {
        var p = createElement("param");
        p.setAttribute("name", pName);
        p.setAttribute("value", pValue);
        el.appendChild(p);
    }


    function removeSWF(id) {
        var obj = getElementById(id);
        if (obj && obj.nodeName == "OBJECT") {
            if (ua.ie && ua.win) {
                obj.style.display = "none";
                (function () {
                    if (obj.readyState == 4) {
                        removeObjectInIE(id);
                    }
                    else {
                        setTimeout(arguments.callee, 10);
                    }
                })();
            }
            else {
                obj.parentNode.removeChild(obj);
            }
        }
    }

    function removeObjectInIE(id) {
        var obj = getElementById(id);
        if (obj) {
            for (var i in obj) {
                if (typeof obj[i] == "function") {
                    obj[i] = null;
                }
            }
            obj.parentNode.removeChild(obj);
        }
    }


    function getElementById(id) {
        var el = null;
        try {
            el = doc.getElementById(id);
        }
        catch (e) { }
        return el;
    }

    function createElement(el) {
        return doc.createElement(el);
    }


    function addListener(target, eventType, fn) {
        target.attachEvent(eventType, fn);
        listenersArr[listenersArr.length] = [target, eventType, fn];
    }


    function hasPlayerVersion(rv) {
        var pv = ua.pv, v = rv.split(".");
        v[0] = parseInt(v[0], 10);
        v[1] = parseInt(v[1], 10) || 0;
        v[2] = parseInt(v[2], 10) || 0;
        return (pv[0] > v[0] || (pv[0] == v[0] && pv[1] > v[1]) || (pv[0] == v[0] && pv[1] == v[1] && pv[2] >= v[2])) ? true : false;
    }


    function createCSS(sel, decl, media, newStyle) {
        if (ua.ie && ua.mac) { return; }
        var h = doc.getElementsByTagName("head")[0];
        if (!h) { return; }
        var m = (media && typeof media == "string") ? media : "screen";
        if (newStyle) {
            dynamicStylesheet = null;
            dynamicStylesheetMedia = null;
        }
        if (!dynamicStylesheet || dynamicStylesheetMedia != m) {

            var s = createElement("style");
            s.setAttribute("type", "text/css");
            s.setAttribute("media", m);
            dynamicStylesheet = h.appendChild(s);
            if (ua.ie && ua.win && typeof doc.styleSheets != UNDEF && doc.styleSheets.length > 0) {
                dynamicStylesheet = doc.styleSheets[doc.styleSheets.length - 1];
            }
            dynamicStylesheetMedia = m;
        }

        if (ua.ie && ua.win) {
            if (dynamicStylesheet && typeof dynamicStylesheet.addRule == OBJECT) {
                dynamicStylesheet.addRule(sel, decl);
            }
        }
        else {
            if (dynamicStylesheet && typeof doc.createTextNode != UNDEF) {
                dynamicStylesheet.appendChild(doc.createTextNode(sel + " {" + decl + "}"));
            }
        }
    }

    function setVisibility(id, isVisible) {
        if (!autoHideShow) { return; }
        var v = isVisible ? "visible" : "hidden";
        if (isDomLoaded && getElementById(id)) {
            getElementById(id).style.visibility = v;
        }
        else {
            createCSS("#" + id, "visibility:" + v);
        }
    }


    function urlEncodeIfNecessary(s) {
        var regex = /[\\\"<>\.;]/;
        var hasBadChars = regex.exec(s) != null;
        return hasBadChars && typeof encodeURIComponent != UNDEF ? encodeURIComponent(s) : s;
    }


    var cleanup = function () {
        if (ua.ie && ua.win) {
            window.attachEvent("onunload", function () {

                var ll = listenersArr.length;
                for (var i = 0; i < ll; i++) {
                    listenersArr[i][0].detachEvent(listenersArr[i][1], listenersArr[i][2]);
                }

                var il = objIdArr.length;
                for (var j = 0; j < il; j++) {
                    removeSWF(objIdArr[j]);
                }

                for (var k in ua) {
                    ua[k] = null;
                }
                ua = null;
                for (var l in swfobject) {
                    swfobject[l] = null;
                }
                swfobject = null;
            });
        }
    } ();

    return {

        registerObject: function (objectIdStr, swfVersionStr, xiSwfUrlStr, callbackFn) {
            if (ua.w3 && objectIdStr && swfVersionStr) {
                var regObj = {};
                regObj.id = objectIdStr;
                regObj.swfVersion = swfVersionStr;
                regObj.expressInstall = xiSwfUrlStr;
                regObj.callbackFn = callbackFn;
                regObjArr[regObjArr.length] = regObj;
                setVisibility(objectIdStr, false);
            }
            else if (callbackFn) {
                callbackFn({ success: false, id: objectIdStr });
            }
        },

        getObjectById: function (objectIdStr) {
            if (ua.w3) {
                return getObjectById(objectIdStr);
            }
        },

        embedSWF: function (swfUrlStr, replaceElemIdStr, widthStr, heightStr, swfVersionStr, xiSwfUrlStr, flashvarsObj, parObj, attObj, callbackFn) {
            var callbackObj = { success: false, id: replaceElemIdStr };
            if (ua.w3 && !(ua.wk && ua.wk < 312) && swfUrlStr && replaceElemIdStr && widthStr && heightStr && swfVersionStr) {
                setVisibility(replaceElemIdStr, false);
                addDomLoadEvent(function () {
                    widthStr += "";
                    heightStr += "";
                    var att = {};
                    if (attObj && typeof attObj === OBJECT) {
                        for (var i in attObj) {
                            att[i] = attObj[i];
                        }
                    }
                    att.data = swfUrlStr;
                    att.width = widthStr;
                    att.height = heightStr;
                    var par = {};
                    if (parObj && typeof parObj === OBJECT) {
                        for (var j in parObj) {
                            par[j] = parObj[j];
                        }
                    }
                    if (flashvarsObj && typeof flashvarsObj === OBJECT) {
                        for (var k in flashvarsObj) {
                            if (typeof par.flashvars != UNDEF) {
                                par.flashvars += "&" + k + "=" + flashvarsObj[k];
                            }
                            else {
                                par.flashvars = k + "=" + flashvarsObj[k];
                            }
                        }
                    }
                    if (hasPlayerVersion(swfVersionStr)) {
                        var obj = createSWF(att, par, replaceElemIdStr);
                        if (att.id == replaceElemIdStr) {
                            setVisibility(replaceElemIdStr, true);
                        }
                        callbackObj.success = true;
                        callbackObj.ref = obj;
                    }
                    else if (xiSwfUrlStr && canExpressInstall()) {
                        att.data = xiSwfUrlStr;
                        showExpressInstall(att, par, replaceElemIdStr, callbackFn);
                        return;
                    }
                    else {
                        setVisibility(replaceElemIdStr, true);
                    }
                    if (callbackFn) { callbackFn(callbackObj); }
                });
            }
            else if (callbackFn) { callbackFn(callbackObj); }
        },

        switchOffAutoHideShow: function () {
            autoHideShow = false;
        },

        ua: ua,

        getFlashPlayerVersion: function () {
            return { major: ua.pv[0], minor: ua.pv[1], release: ua.pv[2] };
        },

        hasFlashPlayerVersion: hasPlayerVersion,

        createSWF: function (attObj, parObj, replaceElemIdStr) {
            if (ua.w3) {
                return createSWF(attObj, parObj, replaceElemIdStr);
            }
            else {
                return undefined;
            }
        },

        showExpressInstall: function (att, par, replaceElemIdStr, callbackFn) {
            if (ua.w3 && canExpressInstall()) {
                showExpressInstall(att, par, replaceElemIdStr, callbackFn);
            }
        },

        removeSWF: function (objElemIdStr) {
            if (ua.w3) {
                removeSWF(objElemIdStr);
            }
        },

        createCSS: function (selStr, declStr, mediaStr, newStyleBoolean) {
            if (ua.w3) {
                createCSS(selStr, declStr, mediaStr, newStyleBoolean);
            }
        },

        addDomLoadEvent: addDomLoadEvent,

        addLoadEvent: addLoadEvent,

        getQueryParamValue: function (param) {
            var q = doc.location.search || doc.location.hash;
            if (q) {
                if (/\?/.test(q)) { q = q.split("?")[1]; }
                if (param == null) {
                    return urlEncodeIfNecessary(q);
                }
                var pairs = q.split("&");
                for (var i = 0; i < pairs.length; i++) {
                    if (pairs[i].substring(0, pairs[i].indexOf("=")) == param) {
                        return urlEncodeIfNecessary(pairs[i].substring((pairs[i].indexOf("=") + 1)));
                    }
                }
            }
            return "";
        },


        expressInstallCallback: function () {
            if (isExpressInstallActive) {
                var obj = getElementById(EXPRESS_INSTALL_ID);
                if (obj && storedAltContent) {
                    obj.parentNode.replaceChild(storedAltContent, obj);
                    if (storedAltContentId) {
                        setVisibility(storedAltContentId, true);
                        if (ua.ie && ua.win) { storedAltContent.style.display = "block"; }
                    }
                    if (storedCallbackFn) { storedCallbackFn(storedCallbackObj); }
                }
                isExpressInstallActive = false;
            }
        }
    };
} ();

Ext.FlashComponent = Ext.extend(Ext.BoxComponent, {

    flashVersion: '9.0.115',


    backgroundColor: '#ffffff',


    wmode: 'opaque',


    flashVars: undefined,


    flashParams: undefined,


    url: undefined,
    swfId: undefined,
    swfWidth: '100%',
    swfHeight: '100%',


    expressInstall: false,

    initComponent: function () {
        Ext.FlashComponent.superclass.initComponent.call(this);

        this.addEvents(

            'initialize'
        );
    },

    onRender: function () {
        Ext.FlashComponent.superclass.onRender.apply(this, arguments);

        var params = Ext.apply({
            allowScriptAccess: 'always',
            bgcolor: this.backgroundColor,
            wmode: this.wmode
        }, this.flashParams), vars = Ext.apply({
            allowedDomain: document.location.hostname,
            YUISwfId: this.getId(),
            YUIBridgeCallback: 'Ext.FlashEventProxy.onEvent'
        }, this.flashVars);

        new swfobject.embedSWF(this.url, this.id, this.swfWidth, this.swfHeight, this.flashVersion,
            this.expressInstall ? Ext.FlashComponent.EXPRESS_INSTALL_URL : undefined, vars, params);

        this.swf = Ext.getDom(this.id);
        this.el = Ext.get(this.swf);
    },

    getSwfId: function () {
        return this.swfId || (this.swfId = "extswf" + (++Ext.Component.AUTO_ID));
    },

    getId: function () {
        return this.id || (this.id = "extflashcmp" + (++Ext.Component.AUTO_ID));
    },

    onFlashEvent: function (e) {
        switch (e.type) {
            case "swfReady":
                this.initSwf();
                return;
            case "log":
                return;
        }
        e.component = this;
        this.fireEvent(e.type.toLowerCase().replace(/event$/, ''), e);
    },

    initSwf: function () {
        this.onSwfReady(!!this.isInitialized);
        this.isInitialized = true;
        this.fireEvent('initialize', this);
    },

    beforeDestroy: function () {
        if (this.rendered) {
            swfobject.removeSWF(this.swf.id);
        }
        Ext.FlashComponent.superclass.beforeDestroy.call(this);
    },

    onSwfReady: Ext.emptyFn
});


Ext.FlashComponent.EXPRESS_INSTALL_URL = 'http:/' + '/swfobject.googlecode.com/svn/trunk/swfobject/expressInstall.swf';

Ext.reg('flash', Ext.FlashComponent);
Ext.FlashEventProxy = {
    onEvent: function (id, e) {
        var fp = Ext.getCmp(id);
        if (fp) {
            fp.onFlashEvent(e);
        } else {
            arguments.callee.defer(10, this, [id, e]);
        }
    }
};

Ext.chart.Chart = Ext.extend(Ext.FlashComponent, {
    refreshBuffer: 100,




    chartStyle: {
        padding: 10,
        animationEnabled: true,
        font: {
            name: 'Tahoma',
            color: 0x444444,
            size: 11
        },
        dataTip: {
            padding: 5,
            border: {
                color: 0x99bbe8,
                size: 1
            },
            background: {
                color: 0xDAE7F6,
                alpha: .9
            },
            font: {
                name: 'Tahoma',
                color: 0x15428B,
                size: 10,
                bold: true
            }
        }
    },




    extraStyle: null,


    seriesStyles: null,


    disableCaching: Ext.isIE || Ext.isOpera,
    disableCacheParam: '_dc',

    initComponent: function () {
        Ext.chart.Chart.superclass.initComponent.call(this);
        if (!this.url) {
            this.url = Ext.chart.Chart.CHART_URL;
        }
        if (this.disableCaching) {
            this.url = Ext.urlAppend(this.url, String.format('{0}={1}', this.disableCacheParam, new Date().getTime()));
        }
        this.addEvents(
            'itemmouseover',
            'itemmouseout',
            'itemclick',
            'itemdoubleclick',
            'itemdragstart',
            'itemdrag',
            'itemdragend',

            'beforerefresh',

            'refresh'
        );
        this.store = Ext.StoreMgr.lookup(this.store);
    },


    setStyle: function (name, value) {
        this.swf.setStyle(name, Ext.encode(value));
    },


    setStyles: function (styles) {
        this.swf.setStyles(Ext.encode(styles));
    },


    setSeriesStyles: function (styles) {
        this.seriesStyles = styles;
        var s = [];
        Ext.each(styles, function (style) {
            s.push(Ext.encode(style));
        });
        this.swf.setSeriesStyles(s);
    },

    setCategoryNames: function (names) {
        this.swf.setCategoryNames(names);
    },

    setLegendRenderer: function (fn, scope) {
        var chart = this;
        scope = scope || chart;
        chart.removeFnProxy(chart.legendFnName);
        chart.legendFnName = chart.createFnProxy(function (name) {
            return fn.call(scope, name);
        });
        chart.swf.setLegendLabelFunction(chart.legendFnName);
    },

    setTipRenderer: function (fn, scope) {
        var chart = this;
        scope = scope || chart;
        chart.removeFnProxy(chart.tipFnName);
        chart.tipFnName = chart.createFnProxy(function (item, index, series) {
            var record = chart.store.getAt(index);
            return fn.call(scope, chart, record, index, series);
        });
        chart.swf.setDataTipFunction(chart.tipFnName);
    },

    setSeries: function (series) {
        this.series = series;
        this.refresh();
    },


    bindStore: function (store, initial) {
        if (!initial && this.store) {
            if (store !== this.store && this.store.autoDestroy) {
                this.store.destroy();
            } else {
                this.store.un("datachanged", this.refresh, this);
                this.store.un("add", this.delayRefresh, this);
                this.store.un("remove", this.delayRefresh, this);
                this.store.un("update", this.delayRefresh, this);
                this.store.un("clear", this.refresh, this);
            }
        }
        if (store) {
            store = Ext.StoreMgr.lookup(store);
            store.on({
                scope: this,
                datachanged: this.refresh,
                add: this.delayRefresh,
                remove: this.delayRefresh,
                update: this.delayRefresh,
                clear: this.refresh
            });
        }
        this.store = store;
        if (store && !initial) {
            this.refresh();
        }
    },

    onSwfReady: function (isReset) {
        Ext.chart.Chart.superclass.onSwfReady.call(this, isReset);
        var ref;
        this.swf.setType(this.type);

        if (this.chartStyle) {
            this.setStyles(Ext.apply({}, this.extraStyle, this.chartStyle));
        }

        if (this.categoryNames) {
            this.setCategoryNames(this.categoryNames);
        }

        if (this.tipRenderer) {
            ref = this.getFunctionRef(this.tipRenderer);
            this.setTipRenderer(ref.fn, ref.scope);
        }
        if (this.legendRenderer) {
            ref = this.getFunctionRef(this.legendRenderer);
            this.setLegendRenderer(ref.fn, ref.scope);
        }
        if (!isReset) {
            this.bindStore(this.store, true);
        }
        this.refresh.defer(10, this);
    },

    delayRefresh: function () {
        if (!this.refreshTask) {
            this.refreshTask = new Ext.util.DelayedTask(this.refresh, this);
        }
        this.refreshTask.delay(this.refreshBuffer);
    },

    refresh: function () {
        if (this.fireEvent('beforerefresh', this) !== false) {
            var styleChanged = false;

            var data = [], rs = this.store.data.items;
            for (var j = 0, len = rs.length; j < len; j++) {
                data[j] = rs[j].data;
            }


            var dataProvider = [];
            var seriesCount = 0;
            var currentSeries = null;
            var i = 0;
            if (this.series) {
                seriesCount = this.series.length;
                for (i = 0; i < seriesCount; i++) {
                    currentSeries = this.series[i];
                    var clonedSeries = {};
                    for (var prop in currentSeries) {
                        if (prop == "style" && currentSeries.style !== null) {
                            clonedSeries.style = Ext.encode(currentSeries.style);
                            styleChanged = true;




                        } else {
                            clonedSeries[prop] = currentSeries[prop];
                        }
                    }
                    dataProvider.push(clonedSeries);
                }
            }

            if (seriesCount > 0) {
                for (i = 0; i < seriesCount; i++) {
                    currentSeries = dataProvider[i];
                    if (!currentSeries.type) {
                        currentSeries.type = this.type;
                    }
                    currentSeries.dataProvider = data;
                }
            } else {
                dataProvider.push({ type: this.type, dataProvider: data });
            }
            this.swf.setDataProvider(dataProvider);
            if (this.seriesStyles) {
                this.setSeriesStyles(this.seriesStyles);
            }
            this.fireEvent('refresh', this);
        }
    },


    createFnProxy: function (fn) {
        var fnName = 'extFnProxy' + (++Ext.chart.Chart.PROXY_FN_ID);
        Ext.chart.Chart.proxyFunction[fnName] = fn;
        return 'Ext.chart.Chart.proxyFunction.' + fnName;
    },


    removeFnProxy: function (fn) {
        if (!Ext.isEmpty(fn)) {
            fn = fn.replace('Ext.chart.Chart.proxyFunction.', '');
            delete Ext.chart.Chart.proxyFunction[fn];
        }
    },


    getFunctionRef: function (val) {
        if (Ext.isFunction(val)) {
            return {
                fn: val,
                scope: this
            };
        } else {
            return {
                fn: val.fn,
                scope: val.scope || this
            };
        }
    },


    onDestroy: function () {
        if (this.refreshTask && this.refreshTask.cancel) {
            this.refreshTask.cancel();
        }
        Ext.chart.Chart.superclass.onDestroy.call(this);
        this.bindStore(null);
        this.removeFnProxy(this.tipFnName);
        this.removeFnProxy(this.legendFnName);
    }
});
Ext.reg('chart', Ext.chart.Chart);
Ext.chart.Chart.PROXY_FN_ID = 0;
Ext.chart.Chart.proxyFunction = {};


Ext.chart.Chart.CHART_URL = 'http:/' + '/yui.yahooapis.com/2.8.0/build/charts/assets/charts.swf';


Ext.chart.PieChart = Ext.extend(Ext.chart.Chart, {
    type: 'pie',

    onSwfReady: function (isReset) {
        Ext.chart.PieChart.superclass.onSwfReady.call(this, isReset);

        this.setDataField(this.dataField);
        this.setCategoryField(this.categoryField);
    },

    setDataField: function (field) {
        this.dataField = field;
        this.swf.setDataField(field);
    },

    setCategoryField: function (field) {
        this.categoryField = field;
        this.swf.setCategoryField(field);
    }
});
Ext.reg('piechart', Ext.chart.PieChart);


Ext.chart.CartesianChart = Ext.extend(Ext.chart.Chart, {
    onSwfReady: function (isReset) {
        Ext.chart.CartesianChart.superclass.onSwfReady.call(this, isReset);
        this.labelFn = [];
        if (this.xField) {
            this.setXField(this.xField);
        }
        if (this.yField) {
            this.setYField(this.yField);
        }
        if (this.xAxis) {
            this.setXAxis(this.xAxis);
        }
        if (this.xAxes) {
            this.setXAxes(this.xAxes);
        }
        if (this.yAxis) {
            this.setYAxis(this.yAxis);
        }
        if (this.yAxes) {
            this.setYAxes(this.yAxes);
        }
        if (Ext.isDefined(this.constrainViewport)) {
            this.swf.setConstrainViewport(this.constrainViewport);
        }
    },

    setXField: function (value) {
        this.xField = value;
        this.swf.setHorizontalField(value);
    },

    setYField: function (value) {
        this.yField = value;
        this.swf.setVerticalField(value);
    },

    setXAxis: function (value) {
        this.xAxis = this.createAxis('xAxis', value);
        this.swf.setHorizontalAxis(this.xAxis);
    },

    setXAxes: function (value) {
        var axis;
        for (var i = 0; i < value.length; i++) {
            axis = this.createAxis('xAxis' + i, value[i]);
            this.swf.setHorizontalAxis(axis);
        }
    },

    setYAxis: function (value) {
        this.yAxis = this.createAxis('yAxis', value);
        this.swf.setVerticalAxis(this.yAxis);
    },

    setYAxes: function (value) {
        var axis;
        for (var i = 0; i < value.length; i++) {
            axis = this.createAxis('yAxis' + i, value[i]);
            this.swf.setVerticalAxis(axis);
        }
    },

    createAxis: function (axis, value) {
        var o = Ext.apply({}, value),
            ref,
            old;

        if (this[axis]) {
            old = this[axis].labelFunction;
            this.removeFnProxy(old);
            this.labelFn.remove(old);
        }
        if (o.labelRenderer) {
            ref = this.getFunctionRef(o.labelRenderer);
            o.labelFunction = this.createFnProxy(function (v) {
                return ref.fn.call(ref.scope, v);
            });
            delete o.labelRenderer;
            this.labelFn.push(o.labelFunction);
        }
        if (axis.indexOf('xAxis') > -1 && o.position == 'left') {
            o.position = 'bottom';
        }
        return o;
    },

    onDestroy: function () {
        Ext.chart.CartesianChart.superclass.onDestroy.call(this);
        Ext.each(this.labelFn, function (fn) {
            this.removeFnProxy(fn);
        }, this);
    }
});
Ext.reg('cartesianchart', Ext.chart.CartesianChart);


Ext.chart.LineChart = Ext.extend(Ext.chart.CartesianChart, {
    type: 'line'
});
Ext.reg('linechart', Ext.chart.LineChart);


Ext.chart.ColumnChart = Ext.extend(Ext.chart.CartesianChart, {
    type: 'column'
});
Ext.reg('columnchart', Ext.chart.ColumnChart);


Ext.chart.StackedColumnChart = Ext.extend(Ext.chart.CartesianChart, {
    type: 'stackcolumn'
});
Ext.reg('stackedcolumnchart', Ext.chart.StackedColumnChart);


Ext.chart.BarChart = Ext.extend(Ext.chart.CartesianChart, {
    type: 'bar'
});
Ext.reg('barchart', Ext.chart.BarChart);


Ext.chart.StackedBarChart = Ext.extend(Ext.chart.CartesianChart, {
    type: 'stackbar'
});
Ext.reg('stackedbarchart', Ext.chart.StackedBarChart);




Ext.chart.Axis = function (config) {
    Ext.apply(this, config);
};

Ext.chart.Axis.prototype =
{

    type: null,


    orientation: "horizontal",


    reverse: false,


    labelFunction: null,


    hideOverlappingLabels: true,


    labelSpacing: 2
};


Ext.chart.NumericAxis = Ext.extend(Ext.chart.Axis, {
    type: "numeric",


    minimum: NaN,


    maximum: NaN,


    majorUnit: NaN,


    minorUnit: NaN,


    snapToUnits: true,


    alwaysShowZero: true,


    scale: "linear",


    roundMajorUnit: true,


    calculateByLabelSize: true,


    position: 'left',


    adjustMaximumByMajorUnit: true,


    adjustMinimumByMajorUnit: true

});


Ext.chart.TimeAxis = Ext.extend(Ext.chart.Axis, {
    type: "time",


    minimum: null,


    maximum: null,


    majorUnit: NaN,


    majorTimeUnit: null,


    minorUnit: NaN,


    minorTimeUnit: null,


    snapToUnits: true,


    stackingEnabled: false,


    calculateByLabelSize: true

});


Ext.chart.CategoryAxis = Ext.extend(Ext.chart.Axis, {
    type: "category",


    categoryNames: null,


    calculateCategoryCount: false

});


Ext.chart.Series = function (config) { Ext.apply(this, config); };

Ext.chart.Series.prototype =
{

    type: null,


    displayName: null
};


Ext.chart.CartesianSeries = Ext.extend(Ext.chart.Series, {

    xField: null,


    yField: null,


    showInLegend: true,


    axis: 'primary'
});


Ext.chart.ColumnSeries = Ext.extend(Ext.chart.CartesianSeries, {
    type: "column"
});


Ext.chart.LineSeries = Ext.extend(Ext.chart.CartesianSeries, {
    type: "line"
});


Ext.chart.BarSeries = Ext.extend(Ext.chart.CartesianSeries, {
    type: "bar"
});



Ext.chart.PieSeries = Ext.extend(Ext.chart.Series, {
    type: "pie",
    dataField: null,
    categoryField: null
});
Ext.menu.Menu = Ext.extend(Ext.Container, {



    minWidth: 120,

    shadow: 'sides',

    subMenuAlign: 'tl-tr?',

    defaultAlign: 'tl-bl?',

    allowOtherMenus: false,

    ignoreParentClicks: false,

    enableScrolling: true,

    maxHeight: null,

    scrollIncrement: 24,

    showSeparator: true,

    defaultOffsets: [0, 0],


    plain: false,


    floating: true,



    zIndex: 15000,


    hidden: true,


    layout: 'menu',
    hideMode: 'offsets',
    scrollerHeight: 8,
    autoLayout: true,
    defaultType: 'menuitem',
    bufferResize: false,

    initComponent: function () {
        if (Ext.isArray(this.initialConfig)) {
            Ext.apply(this, { items: this.initialConfig });
        }
        this.addEvents(

            'click',

            'mouseover',

            'mouseout',

            'itemclick'
        );
        Ext.menu.MenuMgr.register(this);
        if (this.floating) {
            Ext.EventManager.onWindowResize(this.hide, this);
        } else {
            if (this.initialConfig.hidden !== false) {
                this.hidden = false;
            }
            this.internalDefaults = { hideOnClick: false };
        }
        Ext.menu.Menu.superclass.initComponent.call(this);
        if (this.autoLayout) {
            var fn = this.doLayout.createDelegate(this, []);
            this.on({
                add: fn,
                remove: fn
            });
        }
    },


    getLayoutTarget: function () {
        return this.ul;
    },


    onRender: function (ct, position) {
        if (!ct) {
            ct = Ext.getBody();
        }

        var dh = {
            id: this.getId(),
            cls: 'x-menu ' + ((this.floating) ? 'x-menu-floating x-layer ' : '') + (this.cls || '') + (this.plain ? ' x-menu-plain' : '') + (this.showSeparator ? '' : ' x-menu-nosep'),
            style: this.style,
            cn: [
                { tag: 'a', cls: 'x-menu-focus', href: '#', onclick: 'return false;', tabIndex: '-1' },
                { tag: 'ul', cls: 'x-menu-list' }
            ]
        };
        if (this.floating) {
            this.el = new Ext.Layer({
                shadow: this.shadow,
                dh: dh,
                constrain: false,
                parentEl: ct,
                zindex: this.zIndex
            });
        } else {
            this.el = ct.createChild(dh);
        }
        Ext.menu.Menu.superclass.onRender.call(this, ct, position);

        if (!this.keyNav) {
            this.keyNav = new Ext.menu.MenuNav(this);
        }

        this.focusEl = this.el.child('a.x-menu-focus');
        this.ul = this.el.child('ul.x-menu-list');
        this.mon(this.ul, {
            scope: this,
            click: this.onClick,
            mouseover: this.onMouseOver,
            mouseout: this.onMouseOut
        });
        if (this.enableScrolling) {
            this.mon(this.el, {
                scope: this,
                delegate: '.x-menu-scroller',
                click: this.onScroll,
                mouseover: this.deactivateActive
            });
        }
    },


    findTargetItem: function (e) {
        var t = e.getTarget('.x-menu-list-item', this.ul, true);
        if (t && t.menuItemId) {
            return this.items.get(t.menuItemId);
        }
    },


    onClick: function (e) {
        var t = this.findTargetItem(e);
        if (t) {
            if (t.isFormField) {
                this.setActiveItem(t);
            } else if (t instanceof Ext.menu.BaseItem) {
                if (t.menu && this.ignoreParentClicks) {
                    t.expandMenu();
                    e.preventDefault();
                } else if (t.onClick) {
                    t.onClick(e);
                    this.fireEvent('click', this, t, e);
                }
            }
        }
    },


    setActiveItem: function (item, autoExpand) {
        if (item != this.activeItem) {
            this.deactivateActive();
            if ((this.activeItem = item).isFormField) {
                item.focus();
            } else {
                item.activate(autoExpand);
            }
        } else if (autoExpand) {
            item.expandMenu();
        }
    },

    deactivateActive: function () {
        var a = this.activeItem;
        if (a) {
            if (a.isFormField) {

                if (a.collapse) {
                    a.collapse();
                }
            } else {
                a.deactivate();
            }
            delete this.activeItem;
        }
    },


    tryActivate: function (start, step) {
        var items = this.items;
        for (var i = start, len = items.length; i >= 0 && i < len; i += step) {
            var item = items.get(i);
            if (item.isVisible() && !item.disabled && (item.canActivate || item.isFormField)) {
                this.setActiveItem(item, false);
                return item;
            }
        }
        return false;
    },


    onMouseOver: function (e) {
        var t = this.findTargetItem(e);
        if (t) {
            if (t.canActivate && !t.disabled) {
                this.setActiveItem(t, true);
            }
        }
        this.over = true;
        this.fireEvent('mouseover', this, e, t);
    },


    onMouseOut: function (e) {
        var t = this.findTargetItem(e);
        if (t) {
            if (t == this.activeItem && t.shouldDeactivate && t.shouldDeactivate(e)) {
                this.activeItem.deactivate();
                delete this.activeItem;
            }
        }
        this.over = false;
        this.fireEvent('mouseout', this, e, t);
    },


    onScroll: function (e, t) {
        if (e) {
            e.stopEvent();
        }
        var ul = this.ul.dom, top = Ext.fly(t).is('.x-menu-scroller-top');
        ul.scrollTop += this.scrollIncrement * (top ? -1 : 1);
        if (top ? ul.scrollTop <= 0 : ul.scrollTop + this.activeMax >= ul.scrollHeight) {
            this.onScrollerOut(null, t);
        }
    },


    onScrollerIn: function (e, t) {
        var ul = this.ul.dom, top = Ext.fly(t).is('.x-menu-scroller-top');
        if (top ? ul.scrollTop > 0 : ul.scrollTop + this.activeMax < ul.scrollHeight) {
            Ext.fly(t).addClass(['x-menu-item-active', 'x-menu-scroller-active']);
        }
    },


    onScrollerOut: function (e, t) {
        Ext.fly(t).removeClass(['x-menu-item-active', 'x-menu-scroller-active']);
    },


    show: function (el, pos, parentMenu) {
        if (this.floating) {
            this.parentMenu = parentMenu;
            if (!this.el) {
                this.render();
                this.doLayout(false, true);
            }
            this.showAt(this.el.getAlignToXY(el, pos || this.defaultAlign, this.defaultOffsets), parentMenu);
        } else {
            Ext.menu.Menu.superclass.show.call(this);
        }
    },


    showAt: function (xy, parentMenu) {
        if (this.fireEvent('beforeshow', this) !== false) {
            this.parentMenu = parentMenu;
            if (!this.el) {
                this.render();
            }
            if (this.enableScrolling) {

                this.el.setXY(xy);

                xy[1] = this.constrainScroll(xy[1]);
                xy = [this.el.adjustForConstraints(xy)[0], xy[1]];
            } else {

                xy = this.el.adjustForConstraints(xy);
            }
            this.el.setXY(xy);
            this.el.show();
            Ext.menu.Menu.superclass.onShow.call(this);
            if (Ext.isIE) {

                this.fireEvent('autosize', this);
                if (!Ext.isIE8) {
                    this.el.repaint();
                }
            }
            this.hidden = false;
            this.focus();
            this.fireEvent('show', this);
        }
    },

    constrainScroll: function (y) {
        var max, full = this.ul.setHeight('auto').getHeight(),
            returnY = y, normalY, parentEl, scrollTop, viewHeight;
        if (this.floating) {
            parentEl = Ext.fly(this.el.dom.parentNode);
            scrollTop = parentEl.getScroll().top;
            viewHeight = parentEl.getViewSize().height;


            normalY = y - scrollTop;
            max = this.maxHeight ? this.maxHeight : viewHeight - normalY;
            if (full > viewHeight) {
                max = viewHeight;

                returnY = y - normalY;
            } else if (max < full) {
                returnY = y - (full - max);
                max = full;
            }
        } else {
            max = this.getHeight();
        }

        if (this.maxHeight) {
            max = Math.min(this.maxHeight, max);
        }
        if (full > max && max > 0) {
            this.activeMax = max - this.scrollerHeight * 2 - this.el.getFrameWidth('tb') - Ext.num(this.el.shadowOffset, 0);
            this.ul.setHeight(this.activeMax);
            this.createScrollers();
            this.el.select('.x-menu-scroller').setDisplayed('');
        } else {
            this.ul.setHeight(full);
            this.el.select('.x-menu-scroller').setDisplayed('none');
        }
        this.ul.dom.scrollTop = 0;
        return returnY;
    },

    createScrollers: function () {
        if (!this.scroller) {
            this.scroller = {
                pos: 0,
                top: this.el.insertFirst({
                    tag: 'div',
                    cls: 'x-menu-scroller x-menu-scroller-top',
                    html: '&#160;'
                }),
                bottom: this.el.createChild({
                    tag: 'div',
                    cls: 'x-menu-scroller x-menu-scroller-bottom',
                    html: '&#160;'
                })
            };
            this.scroller.top.hover(this.onScrollerIn, this.onScrollerOut, this);
            this.scroller.topRepeater = new Ext.util.ClickRepeater(this.scroller.top, {
                listeners: {
                    click: this.onScroll.createDelegate(this, [null, this.scroller.top], false)
                }
            });
            this.scroller.bottom.hover(this.onScrollerIn, this.onScrollerOut, this);
            this.scroller.bottomRepeater = new Ext.util.ClickRepeater(this.scroller.bottom, {
                listeners: {
                    click: this.onScroll.createDelegate(this, [null, this.scroller.bottom], false)
                }
            });
        }
    },

    onLayout: function () {
        if (this.isVisible()) {
            if (this.enableScrolling) {
                this.constrainScroll(this.el.getTop());
            }
            if (this.floating) {
                this.el.sync();
            }
        }
    },

    focus: function () {
        if (!this.hidden) {
            this.doFocus.defer(50, this);
        }
    },

    doFocus: function () {
        if (!this.hidden) {
            this.focusEl.focus();
        }
    },


    hide: function (deep) {
        if (!this.isDestroyed) {
            this.deepHide = deep;
            Ext.menu.Menu.superclass.hide.call(this);
            delete this.deepHide;
        }
    },


    onHide: function () {
        Ext.menu.Menu.superclass.onHide.call(this);
        this.deactivateActive();
        if (this.el && this.floating) {
            this.el.hide();
        }
        var pm = this.parentMenu;
        if (this.deepHide === true && pm) {
            if (pm.floating) {
                pm.hide(true);
            } else {
                pm.deactivateActive();
            }
        }
    },


    lookupComponent: function (c) {
        if (Ext.isString(c)) {
            c = (c == 'separator' || c == '-') ? new Ext.menu.Separator() : new Ext.menu.TextItem(c);
            this.applyDefaults(c);
        } else {
            if (Ext.isObject(c)) {
                c = this.getMenuItem(c);
            } else if (c.tagName || c.el) {
                c = new Ext.BoxComponent({
                    el: c
                });
            }
        }
        return c;
    },

    applyDefaults: function (c) {
        if (!Ext.isString(c)) {
            c = Ext.menu.Menu.superclass.applyDefaults.call(this, c);
            var d = this.internalDefaults;
            if (d) {
                if (c.events) {
                    Ext.applyIf(c.initialConfig, d);
                    Ext.apply(c, d);
                } else {
                    Ext.applyIf(c, d);
                }
            }
        }
        return c;
    },


    getMenuItem: function (config) {
        if (!config.isXType) {
            if (!config.xtype && Ext.isBoolean(config.checked)) {
                return new Ext.menu.CheckItem(config);
            }
            return Ext.create(config, this.defaultType);
        }
        return config;
    },


    addSeparator: function () {
        return this.add(new Ext.menu.Separator());
    },


    addElement: function (el) {
        return this.add(new Ext.menu.BaseItem({
            el: el
        }));
    },


    addItem: function (item) {
        return this.add(item);
    },


    addMenuItem: function (config) {
        return this.add(this.getMenuItem(config));
    },


    addText: function (text) {
        return this.add(new Ext.menu.TextItem(text));
    },


    onDestroy: function () {
        Ext.EventManager.removeResizeListener(this.hide, this);
        var pm = this.parentMenu;
        if (pm && pm.activeChild == this) {
            delete pm.activeChild;
        }
        delete this.parentMenu;
        Ext.menu.Menu.superclass.onDestroy.call(this);
        Ext.menu.MenuMgr.unregister(this);
        if (this.keyNav) {
            this.keyNav.disable();
        }
        var s = this.scroller;
        if (s) {
            Ext.destroy(s.topRepeater, s.bottomRepeater, s.top, s.bottom);
        }
        Ext.destroy(
            this.el,
            this.focusEl,
            this.ul
        );
    }
});

Ext.reg('menu', Ext.menu.Menu);


Ext.menu.MenuNav = Ext.extend(Ext.KeyNav, function () {
    function up(e, m) {
        if (!m.tryActivate(m.items.indexOf(m.activeItem) - 1, -1)) {
            m.tryActivate(m.items.length - 1, -1);
        }
    }
    function down(e, m) {
        if (!m.tryActivate(m.items.indexOf(m.activeItem) + 1, 1)) {
            m.tryActivate(0, 1);
        }
    }
    return {
        constructor: function (menu) {
            Ext.menu.MenuNav.superclass.constructor.call(this, menu.el);
            this.scope = this.menu = menu;
        },

        doRelay: function (e, h) {
            var k = e.getKey();

            if (this.menu.activeItem && this.menu.activeItem.isFormField && k != e.TAB) {
                return false;
            }
            if (!this.menu.activeItem && e.isNavKeyPress() && k != e.SPACE && k != e.RETURN) {
                this.menu.tryActivate(0, 1);
                return false;
            }
            return h.call(this.scope || this, e, this.menu);
        },

        tab: function (e, m) {
            e.stopEvent();
            if (e.shiftKey) {
                up(e, m);
            } else {
                down(e, m);
            }
        },

        up: up,

        down: down,

        right: function (e, m) {
            if (m.activeItem) {
                m.activeItem.expandMenu(true);
            }
        },

        left: function (e, m) {
            m.hide();
            if (m.parentMenu && m.parentMenu.activeItem) {
                m.parentMenu.activeItem.activate();
            }
        },

        enter: function (e, m) {
            if (m.activeItem) {
                e.stopPropagation();
                m.activeItem.onClick(e);
                m.fireEvent('click', this, m.activeItem);
                return true;
            }
        }
    };
} ());

Ext.menu.MenuMgr = function () {
    var menus, active, groups = {}, attached = false, lastShow = new Date();


    function init() {
        menus = {};
        active = new Ext.util.MixedCollection();
        Ext.getDoc().addKeyListener(27, function () {
            if (active.length > 0) {
                hideAll();
            }
        });
    }


    function hideAll() {
        if (active && active.length > 0) {
            var c = active.clone();
            c.each(function (m) {
                m.hide();
            });
            return true;
        }
        return false;
    }


    function onHide(m) {
        active.remove(m);
        if (active.length < 1) {
            Ext.getDoc().un("mousedown", onMouseDown);
            attached = false;
        }
    }


    function onShow(m) {
        var last = active.last();
        lastShow = new Date();
        active.add(m);
        if (!attached) {
            Ext.getDoc().on("mousedown", onMouseDown);
            attached = true;
        }
        if (m.parentMenu) {
            m.getEl().setZIndex(parseInt(m.parentMenu.getEl().getStyle("z-index"), 10) + 3);
            m.parentMenu.activeChild = m;
        } else if (last && !last.isDestroyed && last.isVisible()) {
            m.getEl().setZIndex(parseInt(last.getEl().getStyle("z-index"), 10) + 3);
        }
    }


    function onBeforeHide(m) {
        if (m.activeChild) {
            m.activeChild.hide();
        }
        if (m.autoHideTimer) {
            clearTimeout(m.autoHideTimer);
            delete m.autoHideTimer;
        }
    }


    function onBeforeShow(m) {
        var pm = m.parentMenu;
        if (!pm && !m.allowOtherMenus) {
            hideAll();
        } else if (pm && pm.activeChild) {
            pm.activeChild.hide();
        }
    }


    function onMouseDown(e) {
        if (lastShow.getElapsed() > 50 && active.length > 0 && !e.getTarget(".x-menu")) {
            hideAll();
        }
    }

    return {


        hideAll: function () {
            return hideAll();
        },


        register: function (menu) {
            if (!menus) {
                init();
            }
            menus[menu.id] = menu;
            menu.on({
                beforehide: onBeforeHide,
                hide: onHide,
                beforeshow: onBeforeShow,
                show: onShow
            });
        },


        get: function (menu) {
            if (typeof menu == "string") {
                if (!menus) {
                    return null;
                }
                return menus[menu];
            } else if (menu.events) {
                return menu;
            } else if (typeof menu.length == 'number') {
                return new Ext.menu.Menu({ items: menu });
            } else {
                return Ext.create(menu, 'menu');
            }
        },


        unregister: function (menu) {
            delete menus[menu.id];
            menu.un("beforehide", onBeforeHide);
            menu.un("hide", onHide);
            menu.un("beforeshow", onBeforeShow);
            menu.un("show", onShow);
        },


        registerCheckable: function (menuItem) {
            var g = menuItem.group;
            if (g) {
                if (!groups[g]) {
                    groups[g] = [];
                }
                groups[g].push(menuItem);
            }
        },


        unregisterCheckable: function (menuItem) {
            var g = menuItem.group;
            if (g) {
                groups[g].remove(menuItem);
            }
        },


        onCheckChange: function (item, state) {
            if (item.group && state) {
                var group = groups[item.group],
                   i = 0,
                   len = group.length,
                   current;

                for (; i < len; i++) {
                    current = group[i];
                    if (current != item) {
                        current.setChecked(false);
                    }
                }
            }
        },

        getCheckedItem: function (groupId) {
            var g = groups[groupId];
            if (g) {
                for (var i = 0, l = g.length; i < l; i++) {
                    if (g[i].checked) {
                        return g[i];
                    }
                }
            }
            return null;
        },

        setCheckedItem: function (groupId, itemId) {
            var g = groups[groupId];
            if (g) {
                for (var i = 0, l = g.length; i < l; i++) {
                    if (g[i].id == itemId) {
                        g[i].setChecked(true);
                    }
                }
            }
            return null;
        }
    };
} ();

Ext.menu.BaseItem = Ext.extend(Ext.Component, {




    canActivate: false,

    activeClass: "x-menu-item-active",

    hideOnClick: true,

    clickHideDelay: 1,


    ctype: "Ext.menu.BaseItem",


    actionMode: "container",

    initComponent: function () {
        Ext.menu.BaseItem.superclass.initComponent.call(this);
        this.addEvents(

            'click',

            'activate',

            'deactivate'
        );
        if (this.handler) {
            this.on("click", this.handler, this.scope);
        }
    },


    onRender: function (container, position) {
        Ext.menu.BaseItem.superclass.onRender.apply(this, arguments);
        if (this.ownerCt && this.ownerCt instanceof Ext.menu.Menu) {
            this.parentMenu = this.ownerCt;
        } else {
            this.container.addClass('x-menu-list-item');
            this.mon(this.el, {
                scope: this,
                click: this.onClick,
                mouseenter: this.activate,
                mouseleave: this.deactivate
            });
        }
    },


    setHandler: function (handler, scope) {
        if (this.handler) {
            this.un("click", this.handler, this.scope);
        }
        this.on("click", this.handler = handler, this.scope = scope);
    },


    onClick: function (e) {
        if (!this.disabled && this.fireEvent("click", this, e) !== false
                && (this.parentMenu && this.parentMenu.fireEvent("itemclick", this, e) !== false)) {
            this.handleClick(e);
        } else {
            e.stopEvent();
        }
    },


    activate: function () {
        if (this.disabled) {
            return false;
        }
        var li = this.container;
        li.addClass(this.activeClass);
        this.region = li.getRegion().adjust(2, 2, -2, -2);
        this.fireEvent("activate", this);
        return true;
    },


    deactivate: function () {
        this.container.removeClass(this.activeClass);
        this.fireEvent("deactivate", this);
    },


    shouldDeactivate: function (e) {
        return !this.region || !this.region.contains(e.getPoint());
    },


    handleClick: function (e) {
        var pm = this.parentMenu;
        if (this.hideOnClick) {
            if (pm.floating) {
                pm.hide.defer(this.clickHideDelay, pm, [true]);
            } else {
                pm.deactivateActive();
            }
        }
    },


    expandMenu: Ext.emptyFn,


    hideMenu: Ext.emptyFn
});
Ext.reg('menubaseitem', Ext.menu.BaseItem);
Ext.menu.TextItem = Ext.extend(Ext.menu.BaseItem, {


    hideOnClick: false,

    itemCls: "x-menu-text",

    constructor: function (config) {
        if (typeof config == 'string') {
            config = {
                text: config
            };
        }
        Ext.menu.TextItem.superclass.constructor.call(this, config);
    },


    onRender: function () {
        var s = document.createElement("span");
        s.className = this.itemCls;
        s.innerHTML = this.text;
        this.el = s;
        Ext.menu.TextItem.superclass.onRender.apply(this, arguments);
    }
});
Ext.reg('menutextitem', Ext.menu.TextItem);
Ext.menu.Separator = Ext.extend(Ext.menu.BaseItem, {

    itemCls: "x-menu-sep",

    hideOnClick: false,


    activeClass: '',


    onRender: function (li) {
        var s = document.createElement("span");
        s.className = this.itemCls;
        s.innerHTML = "&#160;";
        this.el = s;
        li.addClass("x-menu-sep-li");
        Ext.menu.Separator.superclass.onRender.apply(this, arguments);
    }
});
Ext.reg('menuseparator', Ext.menu.Separator);
Ext.menu.Item = Ext.extend(Ext.menu.BaseItem, {








    itemCls: 'x-menu-item',

    canActivate: true,

    showDelay: 200,


    altText: '',


    hideDelay: 200,


    ctype: 'Ext.menu.Item',

    initComponent: function () {
        Ext.menu.Item.superclass.initComponent.call(this);
        if (this.menu) {
            this.menu = Ext.menu.MenuMgr.get(this.menu);
            this.menu.ownerCt = this;
        }
    },


    onRender: function (container, position) {
        if (!this.itemTpl) {
            this.itemTpl = Ext.menu.Item.prototype.itemTpl = new Ext.XTemplate(
                '<a id="{id}" class="{cls}" hidefocus="true" unselectable="on" href="{href}"',
                    '<tpl if="hrefTarget">',
                        ' target="{hrefTarget}"',
                    '</tpl>',
                 '>',
                     '<img alt="{altText}" src="{icon}" class="x-menu-item-icon {iconCls}"/>',
                     '<span class="x-menu-item-text">{text}</span>',
                 '</a>'
             );
        }
        var a = this.getTemplateArgs();
        this.el = position ? this.itemTpl.insertBefore(position, a, true) : this.itemTpl.append(container, a, true);
        this.iconEl = this.el.child('img.x-menu-item-icon');
        this.textEl = this.el.child('.x-menu-item-text');
        if (!this.href) {
            this.mon(this.el, 'click', Ext.emptyFn, null, { preventDefault: true });
        }
        Ext.menu.Item.superclass.onRender.call(this, container, position);
    },

    getTemplateArgs: function () {
        return {
            id: this.id,
            cls: this.itemCls + (this.menu ? ' x-menu-item-arrow' : '') + (this.cls ? ' ' + this.cls : ''),
            href: this.href || '#',
            hrefTarget: this.hrefTarget,
            icon: this.icon || Ext.BLANK_IMAGE_URL,
            iconCls: this.iconCls || '',
            text: this.itemText || this.text || '&#160;',
            altText: this.altText || ''
        };
    },


    setText: function (text) {
        this.text = text || '&#160;';
        if (this.rendered) {
            this.textEl.update(this.text);
            this.parentMenu.layout.doAutoSize();
        }
    },


    setIconClass: function (cls) {
        var oldCls = this.iconCls;
        this.iconCls = cls;
        if (this.rendered) {
            this.iconEl.replaceClass(oldCls, this.iconCls);
        }
    },


    beforeDestroy: function () {
        if (this.menu) {
            delete this.menu.ownerCt;
            this.menu.destroy();
        }
        Ext.menu.Item.superclass.beforeDestroy.call(this);
    },


    handleClick: function (e) {
        if (!this.href) {
            e.stopEvent();
        }
        Ext.menu.Item.superclass.handleClick.apply(this, arguments);
    },


    activate: function (autoExpand) {
        if (Ext.menu.Item.superclass.activate.apply(this, arguments)) {
            this.focus();
            if (autoExpand) {
                this.expandMenu();
            }
        }
        return true;
    },


    shouldDeactivate: function (e) {
        if (Ext.menu.Item.superclass.shouldDeactivate.call(this, e)) {
            if (this.menu && this.menu.isVisible()) {
                return !this.menu.getEl().getRegion().contains(e.getPoint());
            }
            return true;
        }
        return false;
    },


    deactivate: function () {
        Ext.menu.Item.superclass.deactivate.apply(this, arguments);
        this.hideMenu();
    },


    expandMenu: function (autoActivate) {
        if (!this.disabled && this.menu) {
            clearTimeout(this.hideTimer);
            delete this.hideTimer;
            if (!this.menu.isVisible() && !this.showTimer) {
                this.showTimer = this.deferExpand.defer(this.showDelay, this, [autoActivate]);
            } else if (this.menu.isVisible() && autoActivate) {
                this.menu.tryActivate(0, 1);
            }
        }
    },


    deferExpand: function (autoActivate) {
        delete this.showTimer;
        this.menu.show(this.container, this.parentMenu.subMenuAlign || 'tl-tr?', this.parentMenu);
        if (autoActivate) {
            this.menu.tryActivate(0, 1);
        }
    },


    hideMenu: function () {
        clearTimeout(this.showTimer);
        delete this.showTimer;
        if (!this.hideTimer && this.menu && this.menu.isVisible()) {
            this.hideTimer = this.deferHide.defer(this.hideDelay, this);
        }
    },


    deferHide: function () {
        delete this.hideTimer;
        if (this.menu.over) {
            this.parentMenu.setActiveItem(this, false);
        } else {
            this.menu.hide();
        }
    }
});
Ext.reg('menuitem', Ext.menu.Item);
Ext.menu.CheckItem = Ext.extend(Ext.menu.Item, {


    itemCls: "x-menu-item x-menu-check-item",

    groupClass: "x-menu-group-item",


    checked: false,


    ctype: "Ext.menu.CheckItem",

    initComponent: function () {
        Ext.menu.CheckItem.superclass.initComponent.call(this);
        this.addEvents(

	        "beforecheckchange",

	        "checkchange"
	    );

        if (this.checkHandler) {
            this.on('checkchange', this.checkHandler, this.scope);
        }
        Ext.menu.MenuMgr.registerCheckable(this);
    },


    onRender: function (c) {
        Ext.menu.CheckItem.superclass.onRender.apply(this, arguments);
        if (this.group) {
            this.el.addClass(this.groupClass);
        }
        if (this.checked) {
            this.checked = false;
            this.setChecked(true, true);
        }
    },


    destroy: function () {
        Ext.menu.MenuMgr.unregisterCheckable(this);
        Ext.menu.CheckItem.superclass.destroy.apply(this, arguments);
    },


    setChecked: function (state, suppressEvent) {
        var suppress = suppressEvent === true;
        if (this.checked != state && (suppress || this.fireEvent("beforecheckchange", this, state) !== false)) {
            Ext.menu.MenuMgr.onCheckChange(this, state);
            if (this.container) {
                this.container[state ? "addClass" : "removeClass"]("x-menu-item-checked");
            }
            this.checked = state;
            if (!suppress) {
                this.fireEvent("checkchange", this, state);
            }
        }
    },


    handleClick: function (e) {
        if (!this.disabled && !(this.checked && this.group)) {
            this.setChecked(!this.checked);
        }
        Ext.menu.CheckItem.superclass.handleClick.apply(this, arguments);
    }
});
Ext.reg('menucheckitem', Ext.menu.CheckItem);
Ext.menu.DateMenu = Ext.extend(Ext.menu.Menu, {

    enableScrolling: false,



    hideOnClick: true,


    pickerId: null,




    cls: 'x-date-menu',





    initComponent: function () {
        this.on('beforeshow', this.onBeforeShow, this);
        if (this.strict = (Ext.isIE7 && Ext.isStrict)) {
            this.on('show', this.onShow, this, { single: true, delay: 20 });
        }
        Ext.apply(this, {
            plain: true,
            showSeparator: false,
            items: this.picker = new Ext.DatePicker(Ext.applyIf({
                internalRender: this.strict || !Ext.isIE,
                ctCls: 'x-menu-date-item',
                id: this.pickerId
            }, this.initialConfig))
        });
        this.picker.purgeListeners();
        Ext.menu.DateMenu.superclass.initComponent.call(this);

        this.relayEvents(this.picker, ['select']);
        this.on('show', this.picker.focus, this.picker);
        this.on('select', this.menuHide, this);
        if (this.handler) {
            this.on('select', this.handler, this.scope || this);
        }
    },

    menuHide: function () {
        if (this.hideOnClick) {
            this.hide(true);
        }
    },

    onBeforeShow: function () {
        if (this.picker) {
            this.picker.hideMonthPicker(true);
        }
    },

    onShow: function () {
        var el = this.picker.getEl();
        el.setWidth(el.getWidth());
    }
});
Ext.reg('datemenu', Ext.menu.DateMenu);

Ext.menu.ColorMenu = Ext.extend(Ext.menu.Menu, {

    enableScrolling: false,




    hideOnClick: true,

    cls: 'x-color-menu',


    paletteId: null,










    initComponent: function () {
        Ext.apply(this, {
            plain: true,
            showSeparator: false,
            items: this.palette = new Ext.ColorPalette(Ext.applyIf({
                id: this.paletteId
            }, this.initialConfig))
        });
        this.palette.purgeListeners();
        Ext.menu.ColorMenu.superclass.initComponent.call(this);

        this.relayEvents(this.palette, ['select']);
        this.on('select', this.menuHide, this);
        if (this.handler) {
            this.on('select', this.handler, this.scope || this);
        }
    },

    menuHide: function () {
        if (this.hideOnClick) {
            this.hide(true);
        }
    }
});
Ext.reg('colormenu', Ext.menu.ColorMenu);

Ext.form.Field = Ext.extend(Ext.BoxComponent, {








    invalidClass: 'x-form-invalid',

    invalidText: 'The value in this field is invalid',

    focusClass: 'x-form-focus',


    validationEvent: 'keyup',

    validateOnBlur: true,

    validationDelay: 250,

    defaultAutoCreate: { tag: 'input', type: 'text', size: '20', autocomplete: 'off' },

    fieldClass: 'x-form-field',

    msgTarget: 'qtip',

    msgFx: 'normal',

    readOnly: false,

    disabled: false,

    submitValue: true,


    isFormField: true,


    msgDisplay: '',


    hasFocus: false,


    initComponent: function () {
        Ext.form.Field.superclass.initComponent.call(this);
        this.addEvents(

            'focus',

            'blur',

            'specialkey',

            'change',

            'invalid',

            'valid'
        );
    },


    getName: function () {
        return this.rendered && this.el.dom.name ? this.el.dom.name : this.name || this.id || '';
    },


    onRender: function (ct, position) {
        if (!this.el) {
            var cfg = this.getAutoCreate();

            if (!cfg.name) {
                cfg.name = this.name || this.id;
            }
            if (this.inputType) {
                cfg.type = this.inputType;
            }
            this.autoEl = cfg;
        }
        Ext.form.Field.superclass.onRender.call(this, ct, position);
        if (this.submitValue === false) {
            this.el.dom.removeAttribute('name');
        }
        var type = this.el.dom.type;
        if (type) {
            if (type == 'password') {
                type = 'text';
            }
            this.el.addClass('x-form-' + type);
        }
        if (this.readOnly) {
            this.setReadOnly(true);
        }
        if (this.tabIndex !== undefined) {
            this.el.dom.setAttribute('tabIndex', this.tabIndex);
        }

        this.el.addClass([this.fieldClass, this.cls]);
    },


    getItemCt: function () {
        return this.itemCt;
    },


    initValue: function () {
        if (this.value !== undefined) {
            this.setValue(this.value);
        } else if (!Ext.isEmpty(this.el.dom.value) && this.el.dom.value != this.emptyText) {
            this.setValue(this.el.dom.value);
        }

        this.originalValue = this.getValue();
    },


    isDirty: function () {
        if (this.disabled || !this.rendered) {
            return false;
        }
        return String(this.getValue()) !== String(this.originalValue);
    },


    setReadOnly: function (readOnly) {
        if (this.rendered) {
            this.el.dom.readOnly = readOnly;
        }
        this.readOnly = readOnly;
    },


    afterRender: function () {
        Ext.form.Field.superclass.afterRender.call(this);
        this.initEvents();
        this.initValue();
    },


    fireKey: function (e) {
        if (e.isSpecialKey()) {
            this.fireEvent('specialkey', this, e);
        }
    },


    reset: function () {
        this.setValue(this.originalValue);
        this.clearInvalid();
    },


    initEvents: function () {
        this.mon(this.el, Ext.EventManager.getKeyEvent(), this.fireKey, this);
        this.mon(this.el, 'focus', this.onFocus, this);



        this.mon(this.el, 'blur', this.onBlur, this, this.inEditor ? { buffer: 10} : null);
    },


    preFocus: Ext.emptyFn,


    onFocus: function () {
        this.preFocus();
        if (this.focusClass) {
            this.el.addClass(this.focusClass);
        }
        if (!this.hasFocus) {
            this.hasFocus = true;

            this.startValue = this.getValue();
            this.fireEvent('focus', this);
        }
    },


    beforeBlur: Ext.emptyFn,


    onBlur: function () {
        this.beforeBlur();
        if (this.focusClass) {
            this.el.removeClass(this.focusClass);
        }
        this.hasFocus = false;
        if (this.validationEvent !== false && (this.validateOnBlur || this.validationEvent == 'blur')) {
            this.validate();
        }
        var v = this.getValue();
        if (String(v) !== String(this.startValue)) {
            this.fireEvent('change', this, v, this.startValue);
        }
        this.fireEvent('blur', this);
        this.postBlur();
    },


    postBlur: Ext.emptyFn,


    isValid: function (preventMark) {
        if (this.disabled) {
            return true;
        }
        var restore = this.preventMark;
        this.preventMark = preventMark === true;
        var v = this.validateValue(this.processValue(this.getRawValue()));
        this.preventMark = restore;
        return v;
    },


    validate: function () {
        if (this.disabled || this.validateValue(this.processValue(this.getRawValue()))) {
            this.clearInvalid();
            return true;
        }
        return false;
    },


    processValue: function (value) {
        return value;
    },


    validateValue: function (value) {

        var error = this.getErrors(value)[0];

        if (error == undefined) {
            return true;
        } else {
            this.markInvalid(error);
            return false;
        }
    },


    getErrors: function () {
        return [];
    },


    getActiveError: function () {
        return this.activeError || '';
    },


    markInvalid: function (msg) {

        if (this.rendered && !this.preventMark) {
            msg = msg || this.invalidText;

            var mt = this.getMessageHandler();
            if (mt) {
                mt.mark(this, msg);
            } else if (this.msgTarget) {
                this.el.addClass(this.invalidClass);
                var t = Ext.getDom(this.msgTarget);
                if (t) {
                    t.innerHTML = msg;
                    t.style.display = this.msgDisplay;
                }
            }
        }

        this.setActiveError(msg);
    },


    clearInvalid: function () {

        if (this.rendered && !this.preventMark) {
            this.el.removeClass(this.invalidClass);
            var mt = this.getMessageHandler();
            if (mt) {
                mt.clear(this);
            } else if (this.msgTarget) {
                this.el.removeClass(this.invalidClass);
                var t = Ext.getDom(this.msgTarget);
                if (t) {
                    t.innerHTML = '';
                    t.style.display = 'none';
                }
            }
        }

        this.unsetActiveError();
    },


    setActiveError: function (msg, suppressEvent) {
        this.activeError = msg;
        if (suppressEvent !== true) this.fireEvent('invalid', this, msg);
    },


    unsetActiveError: function (suppressEvent) {
        delete this.activeError;
        if (suppressEvent !== true) this.fireEvent('valid', this);
    },


    getMessageHandler: function () {
        return Ext.form.MessageTargets[this.msgTarget];
    },


    getErrorCt: function () {
        return this.el.findParent('.x-form-element', 5, true) ||
            this.el.findParent('.x-form-field-wrap', 5, true);
    },


    alignErrorEl: function () {
        this.errorEl.setWidth(this.getErrorCt().getWidth(true) - 20);
    },


    alignErrorIcon: function () {
        this.errorIcon.alignTo(this.el, 'tl-tr', [2, 0]);
    },


    getRawValue: function () {
        var v = this.rendered ? this.el.getValue() : Ext.value(this.value, '');
        if (v === this.emptyText) {
            v = '';
        }
        return v;
    },


    getValue: function () {
        if (!this.rendered) {
            return this.value;
        }
        var v = this.el.getValue();
        if (v === this.emptyText || v === undefined) {
            v = '';
        }
        return v;
    },


    setRawValue: function (v) {
        return this.rendered ? (this.el.dom.value = (Ext.isEmpty(v) ? '' : v)) : '';
    },


    setValue: function (v) {
        this.value = v;
        if (this.rendered) {
            this.el.dom.value = (Ext.isEmpty(v) ? '' : v);
            this.validate();
        }
        return this;
    },


    append: function (v) {
        this.setValue([this.getValue(), v].join(''));
    }





});


Ext.form.MessageTargets = {
    'qtip': {
        mark: function (field, msg) {
            field.el.addClass(field.invalidClass);
            field.el.dom.qtip = msg;
            field.el.dom.qclass = 'x-form-invalid-tip';
            if (Ext.QuickTips) {
                Ext.QuickTips.enable();
            }
        },
        clear: function (field) {
            field.el.removeClass(field.invalidClass);
            field.el.dom.qtip = '';
        }
    },
    'title': {
        mark: function (field, msg) {
            field.el.addClass(field.invalidClass);
            field.el.dom.title = msg;
        },
        clear: function (field) {
            field.el.dom.title = '';
        }
    },
    'under': {
        mark: function (field, msg) {
            field.el.addClass(field.invalidClass);
            if (!field.errorEl) {
                var elp = field.getErrorCt();
                if (!elp) {
                    field.el.dom.title = msg;
                    return;
                }
                field.errorEl = elp.createChild({ cls: 'x-form-invalid-msg' });
                field.on('resize', field.alignErrorEl, field);
                field.on('destroy', function () {
                    Ext.destroy(this.errorEl);
                }, field);
            }
            field.alignErrorEl();
            field.errorEl.update(msg);
            Ext.form.Field.msgFx[field.msgFx].show(field.errorEl, field);
        },
        clear: function (field) {
            field.el.removeClass(field.invalidClass);
            if (field.errorEl) {
                Ext.form.Field.msgFx[field.msgFx].hide(field.errorEl, field);
            } else {
                field.el.dom.title = '';
            }
        }
    },
    'side': {
        mark: function (field, msg) {
            field.el.addClass(field.invalidClass);
            if (!field.errorIcon) {
                var elp = field.getErrorCt();

                if (!elp) {
                    field.el.dom.title = msg;
                    return;
                }
                field.errorIcon = elp.createChild({ cls: 'x-form-invalid-icon' });
                if (field.ownerCt) {
                    field.ownerCt.on('afterlayout', field.alignErrorIcon, field);
                    field.ownerCt.on('expand', field.alignErrorIcon, field);
                }
                field.on('resize', field.alignErrorIcon, field);
                field.on('destroy', function () {
                    Ext.destroy(this.errorIcon);
                }, field);
            }
            field.alignErrorIcon();
            field.errorIcon.dom.qtip = msg;
            field.errorIcon.dom.qclass = 'x-form-invalid-tip';
            field.errorIcon.show();
        },
        clear: function (field) {
            field.el.removeClass(field.invalidClass);
            if (field.errorIcon) {
                field.errorIcon.dom.qtip = '';
                field.errorIcon.hide();
            } else {
                field.el.dom.title = '';
            }
        }
    }
};


Ext.form.Field.msgFx = {
    normal: {
        show: function (msgEl, f) {
            msgEl.setDisplayed('block');
        },

        hide: function (msgEl, f) {
            msgEl.setDisplayed(false).update('');
        }
    },

    slide: {
        show: function (msgEl, f) {
            msgEl.slideIn('t', { stopFx: true });
        },

        hide: function (msgEl, f) {
            msgEl.slideOut('t', { stopFx: true, useDisplay: true });
        }
    },

    slideRight: {
        show: function (msgEl, f) {
            msgEl.fixDisplay();
            msgEl.alignTo(f.el, 'tl-tr');
            msgEl.slideIn('l', { stopFx: true });
        },

        hide: function (msgEl, f) {
            msgEl.slideOut('l', { stopFx: true, useDisplay: true });
        }
    }
};
Ext.reg('field', Ext.form.Field);

Ext.form.TextField = Ext.extend(Ext.form.Field, {



    grow: false,

    growMin: 30,

    growMax: 800,

    vtype: null,

    maskRe: null,

    disableKeyFilter: false,

    allowBlank: true,

    minLength: 0,

    maxLength: Number.MAX_VALUE,

    minLengthText: 'The minimum length for this field is {0}',

    maxLengthText: 'The maximum length for this field is {0}',

    selectOnFocus: false,

    blankText: 'This field is required',

    validator: null,

    regex: null,

    regexText: '',

    emptyText: null,

    emptyClass: 'x-form-empty-field',



    initComponent: function () {
        Ext.form.TextField.superclass.initComponent.call(this);
        this.addEvents(

            'autosize',


            'keydown',

            'keyup',

            'keypress'
        );
    },


    initEvents: function () {
        Ext.form.TextField.superclass.initEvents.call(this);
        if (this.validationEvent == 'keyup') {
            this.validationTask = new Ext.util.DelayedTask(this.validate, this);
            this.mon(this.el, 'keyup', this.filterValidation, this);
        }
        else if (this.validationEvent !== false && this.validationEvent != 'blur') {
            this.mon(this.el, this.validationEvent, this.validate, this, { buffer: this.validationDelay });
        }
        if (this.selectOnFocus || this.emptyText) {
            this.mon(this.el, 'mousedown', this.onMouseDown, this);

            if (this.emptyText) {
                this.applyEmptyText();
            }
        }
        if (this.maskRe || (this.vtype && this.disableKeyFilter !== true && (this.maskRe = Ext.form.VTypes[this.vtype + 'Mask']))) {
            this.mon(this.el, 'keypress', this.filterKeys, this);
        }
        if (this.grow) {
            this.mon(this.el, 'keyup', this.onKeyUpBuffered, this, { buffer: 50 });
            this.mon(this.el, 'click', this.autoSize, this);
        }
        if (this.enableKeyEvents) {
            this.mon(this.el, {
                scope: this,
                keyup: this.onKeyUp,
                keydown: this.onKeyDown,
                keypress: this.onKeyPress
            });
        }
    },

    onMouseDown: function (e) {
        if (!this.hasFocus) {
            this.mon(this.el, 'mouseup', Ext.emptyFn, this, { single: true, preventDefault: true });
        }
    },

    processValue: function (value) {
        if (this.stripCharsRe) {
            var newValue = value.replace(this.stripCharsRe, '');
            if (newValue !== value) {
                this.setRawValue(newValue);
                return newValue;
            }
        }
        return value;
    },

    filterValidation: function (e) {
        if (!e.isNavKeyPress()) {
            this.validationTask.delay(this.validationDelay);
        }
    },


    onDisable: function () {
        Ext.form.TextField.superclass.onDisable.call(this);
        if (Ext.isIE) {
            this.el.dom.unselectable = 'on';
        }
    },


    onEnable: function () {
        Ext.form.TextField.superclass.onEnable.call(this);
        if (Ext.isIE) {
            this.el.dom.unselectable = '';
        }
    },


    onKeyUpBuffered: function (e) {
        if (this.doAutoSize(e)) {
            this.autoSize();
        }
    },


    doAutoSize: function (e) {
        return !e.isNavKeyPress();
    },


    onKeyUp: function (e) {
        this.fireEvent('keyup', this, e);
    },


    onKeyDown: function (e) {
        this.fireEvent('keydown', this, e);
    },


    onKeyPress: function (e) {
        this.fireEvent('keypress', this, e);
    },


    reset: function () {
        Ext.form.TextField.superclass.reset.call(this);
        this.applyEmptyText();
    },

    applyEmptyText: function () {
        if (this.rendered && this.emptyText && this.getRawValue().length < 1 && !this.hasFocus) {
            this.setRawValue(this.emptyText);
            this.el.addClass(this.emptyClass);
        }
    },


    preFocus: function () {
        var el = this.el,
            isEmpty;
        if (this.emptyText) {
            if (el.dom.value == this.emptyText) {
                this.setRawValue('');
                isEmpty = true;
            }
            el.removeClass(this.emptyClass);
        }
        if (this.selectOnFocus || isEmpty) {
            el.dom.select();
        }
    },


    postBlur: function () {
        this.applyEmptyText();
    },


    filterKeys: function (e) {
        if (e.ctrlKey) {
            return;
        }
        var k = e.getKey();
        if (Ext.isGecko && (e.isNavKeyPress() || k == e.BACKSPACE || (k == e.DELETE && e.button == -1))) {
            return;
        }
        var cc = String.fromCharCode(e.getCharCode());
        if (!Ext.isGecko && e.isSpecialKey() && !cc) {
            return;
        }
        if (!this.maskRe.test(cc)) {
            e.stopEvent();
        }
    },

    setValue: function (v) {
        if (this.emptyText && this.el && !Ext.isEmpty(v)) {
            this.el.removeClass(this.emptyClass);
        }
        Ext.form.TextField.superclass.setValue.apply(this, arguments);
        this.applyEmptyText();
        this.autoSize();
        return this;
    },


    getErrors: function (value) {
        var errors = Ext.form.TextField.superclass.getErrors.apply(this, arguments);

        value = Ext.isDefined(value) ? value : this.processValue(this.getRawValue());

        if (Ext.isFunction(this.validator)) {
            var msg = this.validator(value);
            if (msg !== true) {
                errors.push(msg);
            }
        }

        if (value.length < 1 || value === this.emptyText) {
            if (this.allowBlank) {

                return errors;
            } else {
                errors.push(this.blankText);
            }
        }

        if (!this.allowBlank && (value.length < 1 || value === this.emptyText)) {
            errors.push(this.blankText);
        }

        if (value.length < this.minLength) {
            errors.push(String.format(this.minLengthText, this.minLength));
        }

        if (value.length > this.maxLength) {
            errors.push(String.format(this.maxLengthText, this.maxLength));
        }

        if (this.vtype) {
            var vt = Ext.form.VTypes;
            if (!vt[this.vtype](value, this)) {
                errors.push(this.vtypeText || vt[this.vtype + 'Text']);
            }
        }

        if (this.regex && !this.regex.test(value)) {
            errors.push(this.regexText);
        }

        return errors;
    },


    selectText: function (start, end) {
        var v = this.getRawValue();
        var doFocus = false;
        if (v.length > 0) {
            start = start === undefined ? 0 : start;
            end = end === undefined ? v.length : end;
            var d = this.el.dom;
            if (d.setSelectionRange) {
                d.setSelectionRange(start, end);
            } else if (d.createTextRange) {
                var range = d.createTextRange();
                range.moveStart('character', start);
                range.moveEnd('character', end - v.length);
                range.select();
            }
            doFocus = Ext.isGecko || Ext.isOpera;
        } else {
            doFocus = true;
        }
        if (doFocus) {
            this.focus();
        }
    },


    autoSize: function () {
        if (!this.grow || !this.rendered) {
            return;
        }
        if (!this.metrics) {
            this.metrics = Ext.util.TextMetrics.createInstance(this.el);
        }
        var el = this.el;
        var v = el.dom.value;
        var d = document.createElement('div');
        d.appendChild(document.createTextNode(v));
        v = d.innerHTML;
        Ext.removeNode(d);
        d = null;
        v += '&#160;';
        var w = Math.min(this.growMax, Math.max(this.metrics.getWidth(v) + 10, this.growMin));
        this.el.setWidth(w);
        this.fireEvent('autosize', this, w);
    },

    onDestroy: function () {
        if (this.validationTask) {
            this.validationTask.cancel();
            this.validationTask = null;
        }
        Ext.form.TextField.superclass.onDestroy.call(this);
    }
});
Ext.reg('textfield', Ext.form.TextField);

Ext.form.TriggerField = Ext.extend(Ext.form.TextField, {



    defaultAutoCreate: { tag: "input", type: "text", size: "16", autocomplete: "off" },

    hideTrigger: false,

    editable: true,

    readOnly: false,

    wrapFocusClass: 'x-trigger-wrap-focus',

    autoSize: Ext.emptyFn,

    monitorTab: true,

    deferHeight: true,

    mimicing: false,

    actionMode: 'wrap',

    defaultTriggerWidth: 17,


    onResize: function (w, h) {
        Ext.form.TriggerField.superclass.onResize.call(this, w, h);
        var tw = this.getTriggerWidth();
        if (Ext.isNumber(w)) {
            this.el.setWidth(w - tw);
        }
        this.wrap.setWidth(this.el.getWidth() + tw);
    },

    getTriggerWidth: function () {
        var tw = this.trigger.getWidth();
        if (!this.hideTrigger && !this.readOnly && tw === 0) {
            tw = this.defaultTriggerWidth;
        }
        return tw;
    },


    alignErrorIcon: function () {
        if (this.wrap) {
            this.errorIcon.alignTo(this.wrap, 'tl-tr', [2, 0]);
        }
    },


    onRender: function (ct, position) {
        this.doc = Ext.isIE ? Ext.getBody() : Ext.getDoc();
        Ext.form.TriggerField.superclass.onRender.call(this, ct, position);

        this.wrap = this.el.wrap({ cls: 'x-form-field-wrap x-form-field-trigger-wrap' });
        this.trigger = this.wrap.createChild(this.triggerConfig ||
                { tag: "img", src: Ext.BLANK_IMAGE_URL, alt: "", cls: "x-form-trigger " + this.triggerClass });
        this.initTrigger();
        if (!this.width) {
            this.wrap.setWidth(this.el.getWidth() + this.trigger.getWidth());
        }
        this.resizeEl = this.positionEl = this.wrap;
    },

    getWidth: function () {
        return (this.el.getWidth() + this.trigger.getWidth());
    },

    updateEditState: function () {
        if (this.rendered) {
            if (this.readOnly) {
                this.el.dom.readOnly = true;
                this.el.addClass('x-trigger-noedit');
                this.mun(this.el, 'click', this.onTriggerClick, this);
                this.trigger.setDisplayed(false);
            } else {
                if (!this.editable) {
                    this.el.dom.readOnly = true;
                    this.el.addClass('x-trigger-noedit');
                    this.mon(this.el, 'click', this.onTriggerClick, this);
                } else {
                    this.el.dom.readOnly = false;
                    this.el.removeClass('x-trigger-noedit');
                    this.mun(this.el, 'click', this.onTriggerClick, this);
                }
                this.trigger.setDisplayed(!this.hideTrigger);
            }
            this.onResize(this.width || this.wrap.getWidth());
        }
    },


    setHideTrigger: function (hideTrigger) {
        if (hideTrigger != this.hideTrigger) {
            this.hideTrigger = hideTrigger;
            this.updateEditState();
        }
    },


    setEditable: function (editable) {
        if (editable != this.editable) {
            this.editable = editable;
            this.updateEditState();
        }
    },


    setReadOnly: function (readOnly) {
        if (readOnly != this.readOnly) {
            this.readOnly = readOnly;
            this.updateEditState();
        }
    },

    afterRender: function () {
        Ext.form.TriggerField.superclass.afterRender.call(this);
        this.updateEditState();
    },


    initTrigger: function () {
        this.mon(this.trigger, 'click', this.onTriggerClick, this, { preventDefault: true });
        this.trigger.addClassOnOver('x-form-trigger-over');
        this.trigger.addClassOnClick('x-form-trigger-click');
    },


    onDestroy: function () {
        Ext.destroy(this.trigger, this.wrap);
        if (this.mimicing) {
            this.doc.un('mousedown', this.mimicBlur, this);
        }
        delete this.doc;
        Ext.form.TriggerField.superclass.onDestroy.call(this);
    },


    onFocus: function () {
        Ext.form.TriggerField.superclass.onFocus.call(this);
        if (!this.mimicing) {
            this.wrap.addClass(this.wrapFocusClass);
            this.mimicing = true;
            this.doc.on('mousedown', this.mimicBlur, this, { delay: 10 });
            if (this.monitorTab) {
                this.on('specialkey', this.checkTab, this);
            }
        }
    },


    checkTab: function (me, e) {
        if (e.getKey() == e.TAB) {
            this.triggerBlur();
        }
    },


    onBlur: Ext.emptyFn,


    mimicBlur: function (e) {
        if (!this.isDestroyed && !this.wrap.contains(e.target) && this.validateBlur(e)) {
            this.triggerBlur();
        }
    },


    triggerBlur: function () {
        this.mimicing = false;
        this.doc.un('mousedown', this.mimicBlur, this);
        if (this.monitorTab && this.el) {
            this.un('specialkey', this.checkTab, this);
        }
        Ext.form.TriggerField.superclass.onBlur.call(this);
        if (this.wrap) {
            this.wrap.removeClass(this.wrapFocusClass);
        }
    },

    beforeBlur: Ext.emptyFn,



    validateBlur: function (e) {
        return true;
    },


    onTriggerClick: Ext.emptyFn




});


Ext.form.TwinTriggerField = Ext.extend(Ext.form.TriggerField, {




    initComponent: function () {
        Ext.form.TwinTriggerField.superclass.initComponent.call(this);

        this.triggerConfig = {
            tag: 'span', cls: 'x-form-twin-triggers', cn: [
            { tag: "img", src: Ext.BLANK_IMAGE_URL, alt: "", cls: "x-form-trigger " + this.trigger1Class },
            { tag: "img", src: Ext.BLANK_IMAGE_URL, alt: "", cls: "x-form-trigger " + this.trigger2Class }
        ]
        };
    },

    getTrigger: function (index) {
        return this.triggers[index];
    },

    afterRender: function () {
        Ext.form.TwinTriggerField.superclass.afterRender.call(this);
        var triggers = this.triggers,
            i = 0,
            len = triggers.length;

        for (; i < len; ++i) {
            if (this['hideTrigger' + (i + 1)]) {
                triggers[i].hide();
            }

        }
    },

    initTrigger: function () {
        var ts = this.trigger.select('.x-form-trigger', true),
            triggerField = this;

        ts.each(function (t, all, index) {
            var triggerIndex = 'Trigger' + (index + 1);
            t.hide = function () {
                var w = triggerField.wrap.getWidth();
                this.dom.style.display = 'none';
                triggerField.el.setWidth(w - triggerField.trigger.getWidth());
                triggerField['hidden' + triggerIndex] = true;
            };
            t.show = function () {
                var w = triggerField.wrap.getWidth();
                this.dom.style.display = '';
                triggerField.el.setWidth(w - triggerField.trigger.getWidth());
                triggerField['hidden' + triggerIndex] = false;
            };
            this.mon(t, 'click', this['on' + triggerIndex + 'Click'], this, { preventDefault: true });
            t.addClassOnOver('x-form-trigger-over');
            t.addClassOnClick('x-form-trigger-click');
        }, this);
        this.triggers = ts.elements;
    },

    getTriggerWidth: function () {
        var tw = 0;
        Ext.each(this.triggers, function (t, index) {
            var triggerIndex = 'Trigger' + (index + 1),
                w = t.getWidth();
            if (w === 0 && !this['hidden' + triggerIndex]) {
                tw += this.defaultTriggerWidth;
            } else {
                tw += w;
            }
        }, this);
        return tw;
    },


    onDestroy: function () {
        Ext.destroy(this.triggers);
        Ext.form.TwinTriggerField.superclass.onDestroy.call(this);
    },


    onTrigger1Click: Ext.emptyFn,

    onTrigger2Click: Ext.emptyFn
});
Ext.reg('trigger', Ext.form.TriggerField);

Ext.form.TextArea = Ext.extend(Ext.form.TextField, {

    growMin: 60,

    growMax: 1000,
    growAppend: '&#160;\n&#160;',

    enterIsSpecial: false,


    preventScrollbars: false,



    onRender: function (ct, position) {
        if (!this.el) {
            this.defaultAutoCreate = {
                tag: "textarea",
                style: "width:100px;height:60px;",
                autocomplete: "off"
            };
        }
        Ext.form.TextArea.superclass.onRender.call(this, ct, position);
        if (this.grow) {
            this.textSizeEl = Ext.DomHelper.append(document.body, {
                tag: "pre", cls: "x-form-grow-sizer"
            });
            if (this.preventScrollbars) {
                this.el.setStyle("overflow", "hidden");
            }
            this.el.setHeight(this.growMin);
        }
    },

    onDestroy: function () {
        Ext.removeNode(this.textSizeEl);
        Ext.form.TextArea.superclass.onDestroy.call(this);
    },

    fireKey: function (e) {
        if (e.isSpecialKey() && (this.enterIsSpecial || (e.getKey() != e.ENTER || e.hasModifier()))) {
            this.fireEvent("specialkey", this, e);
        }
    },


    doAutoSize: function (e) {
        return !e.isNavKeyPress() || e.getKey() == e.ENTER;
    },


    filterValidation: function (e) {
        if (!e.isNavKeyPress() || (!this.enterIsSpecial && e.keyCode == e.ENTER)) {
            this.validationTask.delay(this.validationDelay);
        }
    },


    autoSize: function () {
        if (!this.grow || !this.textSizeEl) {
            return;
        }
        var el = this.el,
            v = Ext.util.Format.htmlEncode(el.dom.value),
            ts = this.textSizeEl,
            h;

        Ext.fly(ts).setWidth(this.el.getWidth());
        if (v.length < 1) {
            v = "&#160;&#160;";
        } else {
            v += this.growAppend;
            if (Ext.isIE) {
                v = v.replace(/\n/g, '&#160;<br />');
            }
        }
        ts.innerHTML = v;
        h = Math.min(this.growMax, Math.max(ts.offsetHeight, this.growMin));
        if (h != this.lastHeight) {
            this.lastHeight = h;
            this.el.setHeight(h);
            this.fireEvent("autosize", this, h);
        }
    }
});
Ext.reg('textarea', Ext.form.TextArea);
Ext.form.NumberField = Ext.extend(Ext.form.TextField, {



    fieldClass: "x-form-field x-form-num-field",


    allowDecimals: true,


    decimalSeparator: ".",


    decimalPrecision: 2,


    allowNegative: true,


    minValue: Number.NEGATIVE_INFINITY,


    maxValue: Number.MAX_VALUE,


    minText: "The minimum value for this field is {0}",


    maxText: "The maximum value for this field is {0}",


    nanText: "{0} is not a valid number",


    baseChars: "0123456789",


    autoStripChars: false,


    initEvents: function () {
        var allowed = this.baseChars + '';
        if (this.allowDecimals) {
            allowed += this.decimalSeparator;
        }
        if (this.allowNegative) {
            allowed += '-';
        }
        allowed = Ext.escapeRe(allowed);
        this.maskRe = new RegExp('[' + allowed + ']');
        if (this.autoStripChars) {
            this.stripCharsRe = new RegExp('[^' + allowed + ']', 'gi');
        }

        Ext.form.NumberField.superclass.initEvents.call(this);
    },


    getErrors: function (value) {
        var errors = Ext.form.NumberField.superclass.getErrors.apply(this, arguments);

        value = Ext.isDefined(value) ? value : this.processValue(this.getRawValue());

        if (value.length < 1) {
            return errors;
        }

        value = String(value).replace(this.decimalSeparator, ".");

        if (isNaN(value)) {
            errors.push(String.format(this.nanText, value));
        }

        var num = this.parseValue(value);

        if (num < this.minValue) {
            errors.push(String.format(this.minText, this.minValue));
        }

        if (num > this.maxValue) {
            errors.push(String.format(this.maxText, this.maxValue));
        }

        return errors;
    },

    getValue: function () {
        return this.fixPrecision(this.parseValue(Ext.form.NumberField.superclass.getValue.call(this)));
    },

    setValue: function (v) {
        v = this.fixPrecision(v);
        v = Ext.isNumber(v) ? v : parseFloat(String(v).replace(this.decimalSeparator, "."));
        v = isNaN(v) ? '' : String(v).replace(".", this.decimalSeparator);
        return Ext.form.NumberField.superclass.setValue.call(this, v);
    },


    setMinValue: function (value) {
        this.minValue = Ext.num(value, Number.NEGATIVE_INFINITY);
    },


    setMaxValue: function (value) {
        this.maxValue = Ext.num(value, Number.MAX_VALUE);
    },


    parseValue: function (value) {
        value = parseFloat(String(value).replace(this.decimalSeparator, "."));
        return isNaN(value) ? '' : value;
    },


    fixPrecision: function (value) {
        var nan = isNaN(value);

        if (!this.allowDecimals || this.decimalPrecision == -1 || nan || !value) {
            return nan ? '' : value;
        }

        return parseFloat(parseFloat(value).toFixed(this.decimalPrecision));
    },

    beforeBlur: function () {
        var v = this.parseValue(this.getRawValue());

        if (!Ext.isEmpty(v)) {
            this.setValue(v);
        }
    }
});

Ext.reg('numberfield', Ext.form.NumberField);

Ext.form.DateField = Ext.extend(Ext.form.TriggerField, {

    format: "m/d/Y",

    altFormats: "m/d/Y|n/j/Y|n/j/y|m/j/y|n/d/y|m/j/Y|n/d/Y|m-d-y|m-d-Y|m/d|m-d|md|mdy|mdY|d|Y-m-d|n-j|n/j",

    disabledDaysText: "Disabled",

    disabledDatesText: "Disabled",

    minText: "The date in this field must be equal to or after {0}",

    maxText: "The date in this field must be equal to or before {0}",

    invalidText: "{0} is not a valid date - it must be in the format {1}",

    triggerClass: 'x-form-date-trigger',

    showToday: true,


    startDay: 0,








    defaultAutoCreate: { tag: "input", type: "text", size: "10", autocomplete: "off" },



    initTime: '12',

    initTimeFormat: 'H',


    safeParse: function (value, format) {
        if (/[gGhH]/.test(format.replace(/(\\.)/g, ''))) {

            return Date.parseDate(value, format);
        } else {

            var parsedDate = Date.parseDate(value + ' ' + this.initTime, format + ' ' + this.initTimeFormat);

            if (parsedDate) {
                return parsedDate.clearTime();
            }
        }
    },

    initComponent: function () {
        Ext.form.DateField.superclass.initComponent.call(this);

        this.addEvents(

            'select'
        );

        if (Ext.isString(this.minValue)) {
            this.minValue = this.parseDate(this.minValue);
        }
        if (Ext.isString(this.maxValue)) {
            this.maxValue = this.parseDate(this.maxValue);
        }
        this.disabledDatesRE = null;
        this.initDisabledDays();
    },

    initEvents: function () {
        Ext.form.DateField.superclass.initEvents.call(this);
        this.keyNav = new Ext.KeyNav(this.el, {
            "down": function (e) {
                this.onTriggerClick();
            },
            scope: this,
            forceKeyDown: true
        });
    },



    initDisabledDays: function () {
        if (this.disabledDates) {
            var dd = this.disabledDates,
                len = dd.length - 1,
                re = "(?:";

            Ext.each(dd, function (d, i) {
                re += Ext.isDate(d) ? '^' + Ext.escapeRe(d.dateFormat(this.format)) + '$' : dd[i];
                if (i != len) {
                    re += '|';
                }
            }, this);
            this.disabledDatesRE = new RegExp(re + ')');
        }
    },


    setDisabledDates: function (dd) {
        this.disabledDates = dd;
        this.initDisabledDays();
        if (this.menu) {
            this.menu.picker.setDisabledDates(this.disabledDatesRE);
        }
    },


    setDisabledDays: function (dd) {
        this.disabledDays = dd;
        if (this.menu) {
            this.menu.picker.setDisabledDays(dd);
        }
    },


    setMinValue: function (dt) {
        this.minValue = (Ext.isString(dt) ? this.parseDate(dt) : dt);
        if (this.menu) {
            this.menu.picker.setMinDate(this.minValue);
        }
    },


    setMaxValue: function (dt) {
        this.maxValue = (Ext.isString(dt) ? this.parseDate(dt) : dt);
        if (this.menu) {
            this.menu.picker.setMaxDate(this.maxValue);
        }
    },


    getErrors: function (value) {
        var errors = Ext.form.DateField.superclass.getErrors.apply(this, arguments);

        value = this.formatDate(value || this.processValue(this.getRawValue()));

        if (value.length < 1) {
            return errors;
        }

        var svalue = value;
        value = this.parseDate(value);
        if (!value) {
            errors.push(String.format(this.invalidText, svalue, this.format));
            return errors;
        }

        var time = value.getTime();
        if (this.minValue && time < this.minValue.clearTime().getTime()) {
            errors.push(String.format(this.minText, this.formatDate(this.minValue)));
        }

        if (this.maxValue && time > this.maxValue.clearTime().getTime()) {
            errors.push(String.format(this.maxText, this.formatDate(this.maxValue)));
        }

        if (this.disabledDays) {
            var day = value.getDay();

            for (var i = 0; i < this.disabledDays.length; i++) {
                if (day === this.disabledDays[i]) {
                    errors.push(this.disabledDaysText);
                    break;
                }
            }
        }

        var fvalue = this.formatDate(value);
        if (this.disabledDatesRE && this.disabledDatesRE.test(fvalue)) {
            errors.push(String.format(this.disabledDatesText, fvalue));
        }

        return errors;
    },



    validateBlur: function () {
        return !this.menu || !this.menu.isVisible();
    },


    getValue: function () {
        return this.parseDate(Ext.form.DateField.superclass.getValue.call(this)) || "";
    },


    setValue: function (date) {
        return Ext.form.DateField.superclass.setValue.call(this, this.formatDate(this.parseDate(date)));
    },


    parseDate: function (value) {
        if (!value || Ext.isDate(value)) {
            return value;
        }

        var v = this.safeParse(value, this.format),
            af = this.altFormats,
            afa = this.altFormatsArray;

        if (!v && af) {
            afa = afa || af.split("|");

            for (var i = 0, len = afa.length; i < len && !v; i++) {
                v = this.safeParse(value, afa[i]);
            }
        }
        return v;
    },


    onDestroy: function () {
        Ext.destroy(this.menu, this.keyNav);
        Ext.form.DateField.superclass.onDestroy.call(this);
    },


    formatDate: function (date) {
        return Ext.isDate(date) ? date.dateFormat(this.format) : date;
    },




    onTriggerClick: function () {
        if (this.disabled) {
            return;
        }
        if (this.menu == null) {
            this.menu = new Ext.menu.DateMenu({
                hideOnClick: false,
                focusOnSelect: false
            });
        }
        this.onFocus();
        Ext.apply(this.menu.picker, {
            minDate: this.minValue,
            maxDate: this.maxValue,
            disabledDatesRE: this.disabledDatesRE,
            disabledDatesText: this.disabledDatesText,
            disabledDays: this.disabledDays,
            disabledDaysText: this.disabledDaysText,
            format: this.format,
            showToday: this.showToday,
            startDay: this.startDay,
            minText: String.format(this.minText, this.formatDate(this.minValue)),
            maxText: String.format(this.maxText, this.formatDate(this.maxValue))
        });
        this.menu.picker.setValue(this.getValue() || new Date());
        this.menu.show(this.el, "tl-bl?");
        this.menuEvents('on');
    },


    menuEvents: function (method) {
        this.menu[method]('select', this.onSelect, this);
        this.menu[method]('hide', this.onMenuHide, this);
        this.menu[method]('show', this.onFocus, this);
    },

    onSelect: function (m, d) {
        this.setValue(d);
        this.fireEvent('select', this, d);
        this.menu.hide();
    },

    onMenuHide: function () {
        this.focus(false, 60);
        this.menuEvents('un');
    },


    beforeBlur: function () {
        var v = this.parseDate(this.getRawValue());
        if (v) {
            this.setValue(v);
        }
    }





});
Ext.reg('datefield', Ext.form.DateField);

Ext.form.DisplayField = Ext.extend(Ext.form.Field, {
    validationEvent: false,
    validateOnBlur: false,
    defaultAutoCreate: { tag: "div" },

    fieldClass: "x-form-display-field",

    htmlEncode: false,


    initEvents: Ext.emptyFn,

    isValid: function () {
        return true;
    },

    validate: function () {
        return true;
    },

    getRawValue: function () {
        var v = this.rendered ? this.el.dom.innerHTML : Ext.value(this.value, '');
        if (v === this.emptyText) {
            v = '';
        }
        if (this.htmlEncode) {
            v = Ext.util.Format.htmlDecode(v);
        }
        return v;
    },

    getValue: function () {
        return this.getRawValue();
    },

    getName: function () {
        return this.name;
    },

    setRawValue: function (v) {
        if (this.htmlEncode) {
            v = Ext.util.Format.htmlEncode(v);
        }
        return this.rendered ? (this.el.dom.innerHTML = (Ext.isEmpty(v) ? '' : v)) : (this.value = v);
    },

    setValue: function (v) {
        this.setRawValue(v);
        return this;
    }






});

Ext.reg('displayfield', Ext.form.DisplayField);

Ext.form.ComboBox = Ext.extend(Ext.form.TriggerField, {







    defaultAutoCreate: { tag: "input", type: "text", size: "24", autocomplete: "off" },







    listClass: '',

    selectedClass: 'x-combo-selected',

    listEmptyText: '',

    triggerClass: 'x-form-arrow-trigger',

    shadow: 'sides',

    listAlign: 'tl-bl?',

    maxHeight: 300,

    minHeight: 90,

    triggerAction: 'query',

    minChars: 4,

    autoSelect: true,

    typeAhead: false,

    queryDelay: 500,

    pageSize: 0,

    selectOnFocus: false,

    queryParam: 'query',

    loadingText: 'Loading...',

    resizable: false,

    handleHeight: 8,

    allQuery: '',

    mode: 'remote',

    minListWidth: 70,

    forceSelection: false,

    typeAheadDelay: 250,



    lazyInit: true,


    clearFilterOnReset: true,


    submitValue: undefined,




    initComponent: function () {
        Ext.form.ComboBox.superclass.initComponent.call(this);
        this.addEvents(

            'expand',

            'collapse',


            'beforeselect',

            'select',

            'beforequery'
        );
        if (this.transform) {
            var s = Ext.getDom(this.transform);
            if (!this.hiddenName) {
                this.hiddenName = s.name;
            }
            if (!this.store) {
                this.mode = 'local';
                var d = [], opts = s.options;
                for (var i = 0, len = opts.length; i < len; i++) {
                    var o = opts[i],
                        value = (o.hasAttribute ? o.hasAttribute('value') : o.getAttributeNode('value').specified) ? o.value : o.text;
                    if (o.selected && Ext.isEmpty(this.value, true)) {
                        this.value = value;
                    }
                    d.push([value, o.text]);
                }
                this.store = new Ext.data.ArrayStore({
                    idIndex: 0,
                    fields: ['value', 'text'],
                    data: d,
                    autoDestroy: true
                });
                this.valueField = 'value';
                this.displayField = 'text';
            }
            s.name = Ext.id();
            if (!this.lazyRender) {
                this.target = true;
                this.el = Ext.DomHelper.insertBefore(s, this.autoCreate || this.defaultAutoCreate);
                this.render(this.el.parentNode, s);
            }
            Ext.removeNode(s);
        }

        else if (this.store) {
            this.store = Ext.StoreMgr.lookup(this.store);
            if (this.store.autoCreated) {
                this.displayField = this.valueField = 'field1';
                if (!this.store.expandData) {
                    this.displayField = 'field2';
                }
                this.mode = 'local';
            }
        }

        this.selectedIndex = -1;
        if (this.mode == 'local') {
            if (!Ext.isDefined(this.initialConfig.queryDelay)) {
                this.queryDelay = 10;
            }
            if (!Ext.isDefined(this.initialConfig.minChars)) {
                this.minChars = 0;
            }
        }
    },


    onRender: function (ct, position) {
        if (this.hiddenName && !Ext.isDefined(this.submitValue)) {
            this.submitValue = false;
        }
        Ext.form.ComboBox.superclass.onRender.call(this, ct, position);
        if (this.hiddenName) {
            this.hiddenField = this.el.insertSibling({ tag: 'input', type: 'hidden', name: this.hiddenName,
                id: (this.hiddenId || Ext.id())
            }, 'before', true);

        }
        if (Ext.isGecko) {
            this.el.dom.setAttribute('autocomplete', 'off');
        }

        if (!this.lazyInit) {
            this.initList();
        } else {
            this.on('focus', this.initList, this, { single: true });
        }
    },


    initValue: function () {
        Ext.form.ComboBox.superclass.initValue.call(this);
        if (this.hiddenField) {
            this.hiddenField.value =
                Ext.value(Ext.isDefined(this.hiddenValue) ? this.hiddenValue : this.value, '');
        }
    },

    getParentZIndex: function () {
        var zindex;
        if (this.ownerCt) {
            this.findParentBy(function (ct) {
                zindex = parseInt(ct.getPositionEl().getStyle('z-index'), 10);
                return !!zindex;
            });
        }
        return zindex;
    },

    getZIndex: function (listParent) {
        listParent = listParent || Ext.getDom(this.getListParent() || Ext.getBody());
        var zindex = parseInt(Ext.fly(listParent).getStyle('z-index'), 10);
        if (!zindex) {
            zindex = this.getParentZIndex();
        }
        return (zindex || 12000) + 5;
    },


    initList: function () {
        if (!this.list) {
            var cls = 'x-combo-list',
                listParent = Ext.getDom(this.getListParent() || Ext.getBody());

            this.list = new Ext.Layer({
                parentEl: listParent,
                shadow: this.shadow,
                cls: [cls, this.listClass].join(' '),
                constrain: false,
                zindex: this.getZIndex(listParent)
            });

            var lw = this.listWidth || Math.max(this.wrap.getWidth(), this.minListWidth);
            this.list.setSize(lw, 0);
            this.list.swallowEvent('mousewheel');
            this.assetHeight = 0;
            if (this.syncFont !== false) {
                this.list.setStyle('font-size', this.el.getStyle('font-size'));
            }
            if (this.title) {
                this.header = this.list.createChild({ cls: cls + '-hd', html: this.title });
                this.assetHeight += this.header.getHeight();
            }

            this.innerList = this.list.createChild({ cls: cls + '-inner' });
            this.mon(this.innerList, 'mouseover', this.onViewOver, this);
            this.mon(this.innerList, 'mousemove', this.onViewMove, this);
            this.innerList.setWidth(lw - this.list.getFrameWidth('lr'));

            if (this.pageSize) {
                this.footer = this.list.createChild({ cls: cls + '-ft' });
                this.pageTb = new Ext.PagingToolbar({
                    store: this.store,
                    pageSize: this.pageSize,
                    renderTo: this.footer
                });
                this.assetHeight += this.footer.getHeight();
            }

            if (!this.tpl) {

                this.tpl = '<tpl for="."><div class="' + cls + '-item">{' + this.displayField + '}</div></tpl>';

            }


            this.view = new Ext.DataView({
                applyTo: this.innerList,
                tpl: this.tpl,
                singleSelect: true,
                selectedClass: this.selectedClass,
                itemSelector: this.itemSelector || '.' + cls + '-item',
                emptyText: this.listEmptyText,
                deferEmptyText: false
            });

            this.mon(this.view, {
                containerclick: this.onViewClick,
                click: this.onViewClick,
                scope: this
            });

            this.bindStore(this.store, true);

            if (this.resizable) {
                this.resizer = new Ext.Resizable(this.list, {
                    pinned: true, handles: 'se'
                });
                this.mon(this.resizer, 'resize', function (r, w, h) {
                    this.maxHeight = h - this.handleHeight - this.list.getFrameWidth('tb') - this.assetHeight;
                    this.listWidth = w;
                    this.innerList.setWidth(w - this.list.getFrameWidth('lr'));
                    this.restrictHeight();
                }, this);

                this[this.pageSize ? 'footer' : 'innerList'].setStyle('margin-bottom', this.handleHeight + 'px');
            }
        }
    },


    getListParent: function () {
        return document.body;
    },


    getStore: function () {
        return this.store;
    },


    bindStore: function (store, initial) {
        if (this.store && !initial) {
            if (this.store !== store && this.store.autoDestroy) {
                this.store.destroy();
            } else {
                this.store.un('beforeload', this.onBeforeLoad, this);
                this.store.un('load', this.onLoad, this);
                this.store.un('exception', this.collapse, this);
            }
            if (!store) {
                this.store = null;
                if (this.view) {
                    this.view.bindStore(null);
                }
                if (this.pageTb) {
                    this.pageTb.bindStore(null);
                }
            }
        }
        if (store) {
            if (!initial) {
                this.lastQuery = null;
                if (this.pageTb) {
                    this.pageTb.bindStore(store);
                }
            }

            this.store = Ext.StoreMgr.lookup(store);
            this.store.on({
                scope: this,
                beforeload: this.onBeforeLoad,
                load: this.onLoad,
                exception: this.collapse
            });

            if (this.view) {
                this.view.bindStore(store);
            }
        }
    },

    reset: function () {
        if (this.clearFilterOnReset && this.mode == 'local') {
            this.store.clearFilter();
        }
        Ext.form.ComboBox.superclass.reset.call(this);
    },


    initEvents: function () {
        Ext.form.ComboBox.superclass.initEvents.call(this);


        this.keyNav = new Ext.KeyNav(this.el, {
            "up": function (e) {
                this.inKeyMode = true;
                this.selectPrev();
            },

            "down": function (e) {
                if (!this.isExpanded()) {
                    this.onTriggerClick();
                } else {
                    this.inKeyMode = true;
                    this.selectNext();
                }
            },

            "enter": function (e) {
                this.onViewClick();
            },

            "esc": function (e) {
                this.collapse();
            },

            "tab": function (e) {
                if (this.forceSelection === true) {
                    this.collapse();
                } else {
                    this.onViewClick(false);
                }
                return true;
            },

            scope: this,

            doRelay: function (e, h, hname) {
                if (hname == 'down' || this.scope.isExpanded()) {

                    var relay = Ext.KeyNav.prototype.doRelay.apply(this, arguments);
                    if (!Ext.isIE && Ext.EventManager.useKeydown) {

                        this.scope.fireKey(e);
                    }
                    return relay;
                }
                return true;
            },

            forceKeyDown: true,
            defaultEventAction: 'stopEvent'
        });
        this.queryDelay = Math.max(this.queryDelay || 10,
                this.mode == 'local' ? 10 : 250);
        this.dqTask = new Ext.util.DelayedTask(this.initQuery, this);
        if (this.typeAhead) {
            this.taTask = new Ext.util.DelayedTask(this.onTypeAhead, this);
        }
        if (!this.enableKeyEvents) {
            this.mon(this.el, 'keyup', this.onKeyUp, this);
        }
    },



    onDestroy: function () {
        if (this.dqTask) {
            this.dqTask.cancel();
            this.dqTask = null;
        }
        this.bindStore(null);
        Ext.destroy(
            this.resizer,
            this.view,
            this.pageTb,
            this.list
        );
        Ext.destroyMembers(this, 'hiddenField');
        Ext.form.ComboBox.superclass.onDestroy.call(this);
    },


    fireKey: function (e) {
        if (!this.isExpanded()) {
            Ext.form.ComboBox.superclass.fireKey.call(this, e);
        }
    },


    onResize: function (w, h) {
        Ext.form.ComboBox.superclass.onResize.apply(this, arguments);
        if (!isNaN(w) && this.isVisible() && this.list) {
            this.doResize(w);
        } else {
            this.bufferSize = w;
        }
    },

    doResize: function (w) {
        if (!Ext.isDefined(this.listWidth)) {
            var lw = Math.max(w, this.minListWidth);
            this.list.setWidth(lw);
            this.innerList.setWidth(lw - this.list.getFrameWidth('lr'));
        }
    },


    onEnable: function () {
        Ext.form.ComboBox.superclass.onEnable.apply(this, arguments);
        if (this.hiddenField) {
            this.hiddenField.disabled = false;
        }
    },


    onDisable: function () {
        Ext.form.ComboBox.superclass.onDisable.apply(this, arguments);
        if (this.hiddenField) {
            this.hiddenField.disabled = true;
        }
    },


    onBeforeLoad: function () {
        if (!this.hasFocus) {
            return;
        }
        this.innerList.update(this.loadingText ?
               '<div class="loading-indicator">' + this.loadingText + '</div>' : '');
        this.restrictHeight();
        this.selectedIndex = -1;
    },


    onLoad: function () {
        if (!this.hasFocus) {
            return;
        }
        if (this.store.getCount() > 0 || this.listEmptyText) {
            this.expand();
            this.restrictHeight();
            if (this.lastQuery == this.allQuery) {
                if (this.editable) {
                    this.el.dom.select();
                }

                if (this.autoSelect !== false && !this.selectByValue(this.value, true)) {
                    this.select(0, true);
                }
            } else {
                if (this.autoSelect !== false) {
                    this.selectNext();
                }
                if (this.typeAhead && this.lastKey != Ext.EventObject.BACKSPACE && this.lastKey != Ext.EventObject.DELETE) {
                    this.taTask.delay(this.typeAheadDelay);
                }
            }
        } else {
            this.collapse();
        }

    },


    onTypeAhead: function () {
        if (this.store.getCount() > 0) {
            var r = this.store.getAt(0);
            var newValue = r.data[this.displayField];
            var len = newValue.length;
            var selStart = this.getRawValue().length;
            if (selStart != len) {
                this.setRawValue(newValue);
                this.selectText(selStart, newValue.length);
            }
        }
    },


    assertValue: function () {
        var val = this.getRawValue(),
            rec = this.findRecord(this.displayField, val);

        if (!rec && this.forceSelection) {
            if (val.length > 0 && val != this.emptyText) {
                this.el.dom.value = Ext.value(this.lastSelectionText, '');
                this.applyEmptyText();
            } else {
                this.clearValue();
            }
        } else {
            if (rec) {



                if (val == rec.get(this.displayField) && this.value == rec.get(this.valueField)) {
                    return;
                }
                val = rec.get(this.valueField || this.displayField);
            }
            this.setValue(val);
        }
    },


    onSelect: function (record, index) {
        if (this.fireEvent('beforeselect', this, record, index) !== false) {
            this.setValue(record.data[this.valueField || this.displayField]);
            this.collapse();
            this.fireEvent('select', this, record, index);
        }
    },


    getName: function () {
        var hf = this.hiddenField;
        return hf && hf.name ? hf.name : this.hiddenName || Ext.form.ComboBox.superclass.getName.call(this);
    },


    getValue: function () {
        if (this.valueField) {
            return Ext.isDefined(this.value) ? this.value : '';
        } else {
            return Ext.form.ComboBox.superclass.getValue.call(this);
        }
    },


    clearValue: function () {
        if (this.hiddenField) {
            this.hiddenField.value = '';
        }
        this.setRawValue('');
        this.lastSelectionText = '';
        this.applyEmptyText();
        this.value = '';
    },


    setValue: function (v) {
        var text = v;
        if (this.valueField) {
            var r = this.findRecord(this.valueField, v);
            if (r) {
                text = r.data[this.displayField];
            } else if (Ext.isDefined(this.valueNotFoundText)) {
                text = this.valueNotFoundText;
            }
        }
        this.lastSelectionText = text;
        if (this.hiddenField) {
            this.hiddenField.value = Ext.value(v, '');
        }
        Ext.form.ComboBox.superclass.setValue.call(this, text);
        this.value = v;
        return this;
    },


    findRecord: function (prop, value) {
        var record;
        if (this.store.getCount() > 0) {
            this.store.each(function (r) {
                if (r.data[prop] == value) {
                    record = r;
                    return false;
                }
            });
        }
        return record;
    },


    onViewMove: function (e, t) {
        this.inKeyMode = false;
    },


    onViewOver: function (e, t) {
        if (this.inKeyMode) {
            return;
        }
        var item = this.view.findItemFromChild(t);
        if (item) {
            var index = this.view.indexOf(item);
            this.select(index, false);
        }
    },


    onViewClick: function (doFocus) {
        var index = this.view.getSelectedIndexes()[0],
            s = this.store,
            r = s.getAt(index);
        if (r) {
            this.onSelect(r, index);
        } else {
            this.collapse();
        }
        if (doFocus !== false) {
            this.el.focus();
        }
    },



    restrictHeight: function () {
        this.innerList.dom.style.height = '';
        var inner = this.innerList.dom,
            pad = this.list.getFrameWidth('tb') + (this.resizable ? this.handleHeight : 0) + this.assetHeight,
            h = Math.max(inner.clientHeight, inner.offsetHeight, inner.scrollHeight),
            ha = this.getPosition()[1] - Ext.getBody().getScroll().top,
            hb = Ext.lib.Dom.getViewHeight() - ha - this.getSize().height,
            space = Math.max(ha, hb, this.minHeight || 0) - this.list.shadowOffset - pad - 5;

        h = Math.min(h, space, this.maxHeight);

        this.innerList.setHeight(h);
        this.list.beginUpdate();
        this.list.setHeight(h + pad);
        this.list.alignTo.apply(this.list, [this.el].concat(this.listAlign));
        this.list.endUpdate();
    },


    isExpanded: function () {
        return this.list && this.list.isVisible();
    },


    selectByValue: function (v, scrollIntoView) {
        if (!Ext.isEmpty(v, true)) {
            var r = this.findRecord(this.valueField || this.displayField, v);
            if (r) {
                this.select(this.store.indexOf(r), scrollIntoView);
                return true;
            }
        }
        return false;
    },


    select: function (index, scrollIntoView) {
        this.selectedIndex = index;
        this.view.select(index);
        if (scrollIntoView !== false) {
            var el = this.view.getNode(index);
            if (el) {
                this.innerList.scrollChildIntoView(el, false);
            }
        }

    },


    selectNext: function () {
        var ct = this.store.getCount();
        if (ct > 0) {
            if (this.selectedIndex == -1) {
                this.select(0);
            } else if (this.selectedIndex < ct - 1) {
                this.select(this.selectedIndex + 1);
            }
        }
    },


    selectPrev: function () {
        var ct = this.store.getCount();
        if (ct > 0) {
            if (this.selectedIndex == -1) {
                this.select(0);
            } else if (this.selectedIndex !== 0) {
                this.select(this.selectedIndex - 1);
            }
        }
    },


    onKeyUp: function (e) {
        var k = e.getKey();
        if (this.editable !== false && this.readOnly !== true && (k == e.BACKSPACE || !e.isSpecialKey())) {

            this.lastKey = k;
            this.dqTask.delay(this.queryDelay);
        }
        Ext.form.ComboBox.superclass.onKeyUp.call(this, e);
    },


    validateBlur: function () {
        return !this.list || !this.list.isVisible();
    },


    initQuery: function () {
        this.doQuery(this.getRawValue());
    },


    beforeBlur: function () {
        this.assertValue();
    },


    postBlur: function () {
        Ext.form.ComboBox.superclass.postBlur.call(this);
        this.collapse();
        this.inKeyMode = false;
    },


    doQuery: function (q, forceAll) {
        q = Ext.isEmpty(q) ? '' : q;
        var qe = {
            query: q,
            forceAll: forceAll,
            combo: this,
            cancel: false
        };
        if (this.fireEvent('beforequery', qe) === false || qe.cancel) {
            return false;
        }
        q = qe.query;
        forceAll = qe.forceAll;
        if (forceAll === true || (q.length >= this.minChars)) {
            if (this.lastQuery !== q) {
                this.lastQuery = q;
                if (this.mode == 'local') {
                    this.selectedIndex = -1;
                    if (forceAll) {
                        this.store.clearFilter();
                    } else {
                        this.store.filter(this.displayField, q);
                    }
                    this.onLoad();
                } else {
                    this.store.baseParams[this.queryParam] = q;
                    this.store.load({
                        params: this.getParams(q)
                    });
                    this.expand();
                }
            } else {
                this.selectedIndex = -1;
                this.onLoad();
            }
        }
    },


    getParams: function (q) {
        var params = {},
            paramNames = this.store.paramNames;
        if (this.pageSize) {
            params[paramNames.start] = 0;
            params[paramNames.limit] = this.pageSize;
        }
        return params;
    },


    collapse: function () {
        if (!this.isExpanded()) {
            return;
        }
        this.list.hide();
        Ext.getDoc().un('mousewheel', this.collapseIf, this);
        Ext.getDoc().un('mousedown', this.collapseIf, this);
        this.fireEvent('collapse', this);
    },


    collapseIf: function (e) {
        if (!this.isDestroyed && !e.within(this.wrap) && !e.within(this.list)) {
            this.collapse();
        }
    },


    expand: function () {
        if (this.isExpanded() || !this.hasFocus) {
            return;
        }

        if (this.title || this.pageSize) {
            this.assetHeight = 0;
            if (this.title) {
                this.assetHeight += this.header.getHeight();
            }
            if (this.pageSize) {
                this.assetHeight += this.footer.getHeight();
            }
        }

        if (this.bufferSize) {
            this.doResize(this.bufferSize);
            delete this.bufferSize;
        }
        this.list.alignTo.apply(this.list, [this.el].concat(this.listAlign));


        this.list.setZIndex(this.getZIndex());
        this.list.show();
        if (Ext.isGecko2) {
            this.innerList.setOverflow('auto');
        }
        this.mon(Ext.getDoc(), {
            scope: this,
            mousewheel: this.collapseIf,
            mousedown: this.collapseIf
        });
        this.fireEvent('expand', this);
    },




    onTriggerClick: function () {
        if (this.readOnly || this.disabled) {
            return;
        }
        if (this.isExpanded()) {
            this.collapse();
            this.el.focus();
        } else {
            this.onFocus({});
            if (this.triggerAction == 'all') {
                this.doQuery(this.allQuery, true);
            } else {
                this.doQuery(this.getRawValue());
            }
            this.el.focus();
        }
    }






});
Ext.reg('combo', Ext.form.ComboBox);

Ext.form.Checkbox = Ext.extend(Ext.form.Field, {

    focusClass: undefined,

    fieldClass: 'x-form-field',

    checked: false,

    boxLabel: '&#160;',

    defaultAutoCreate: { tag: 'input', type: 'checkbox', autocomplete: 'off' },






    actionMode: 'wrap',


    initComponent: function () {
        Ext.form.Checkbox.superclass.initComponent.call(this);
        this.addEvents(

            'check'
        );
    },


    onResize: function () {
        Ext.form.Checkbox.superclass.onResize.apply(this, arguments);
        if (!this.boxLabel && !this.fieldLabel) {
            this.el.alignTo(this.wrap, 'c-c');
        }
    },


    initEvents: function () {
        Ext.form.Checkbox.superclass.initEvents.call(this);
        this.mon(this.el, {
            scope: this,
            click: this.onClick,
            change: this.onClick
        });
    },


    markInvalid: Ext.emptyFn,

    clearInvalid: Ext.emptyFn,


    onRender: function (ct, position) {
        Ext.form.Checkbox.superclass.onRender.call(this, ct, position);
        if (this.inputValue !== undefined) {
            this.el.dom.value = this.inputValue;
        }
        this.wrap = this.el.wrap({ cls: 'x-form-check-wrap' });
        if (this.boxLabel) {
            this.wrap.createChild({ tag: 'label', htmlFor: this.el.id, cls: 'x-form-cb-label', html: this.boxLabel });
        }
        if (this.checked) {
            this.setValue(true);
        } else {
            this.checked = this.el.dom.checked;
        }

        if (Ext.isIE && !Ext.isStrict) {
            this.wrap.repaint();
        }
        this.resizeEl = this.positionEl = this.wrap;
    },


    onDestroy: function () {
        Ext.destroy(this.wrap);
        Ext.form.Checkbox.superclass.onDestroy.call(this);
    },


    initValue: function () {
        this.originalValue = this.getValue();
    },


    getValue: function () {
        if (this.rendered) {
            return this.el.dom.checked;
        }
        return this.checked;
    },


    onClick: function () {
        if (this.el.dom.checked != this.checked) {
            this.setValue(this.el.dom.checked);
        }
    },


    setValue: function (v) {
        var checked = this.checked,
            inputVal = this.inputValue;

        this.checked = (v === true || v === 'true' || v == '1' || (inputVal ? v == inputVal : String(v).toLowerCase() == 'on'));
        if (this.rendered) {
            this.el.dom.checked = this.checked;
            this.el.dom.defaultChecked = this.checked;
        }
        if (checked != this.checked) {
            this.fireEvent('check', this, this.checked);
            if (this.handler) {
                this.handler.call(this.scope || this, this, this.checked);
            }
        }
        return this;
    }
});
Ext.reg('checkbox', Ext.form.Checkbox);

Ext.form.CheckboxGroup = Ext.extend(Ext.form.Field, {


    columns: 'auto',

    vertical: false,

    allowBlank: true,

    blankText: "You must select at least one item in this group",


    defaultType: 'checkbox',


    groupCls: 'x-form-check-group',


    initComponent: function () {
        this.addEvents(

            'change'
        );
        this.on('change', this.validate, this);
        Ext.form.CheckboxGroup.superclass.initComponent.call(this);
    },


    onRender: function (ct, position) {
        if (!this.el) {
            var panelCfg = {
                autoEl: {
                    id: this.id
                },
                cls: this.groupCls,
                layout: 'column',
                renderTo: ct,
                bufferResize: false
            };
            var colCfg = {
                xtype: 'container',
                defaultType: this.defaultType,
                layout: 'form',
                defaults: {
                    hideLabel: true,
                    anchor: '100%'
                }
            };

            if (this.items[0].items) {



                Ext.apply(panelCfg, {
                    layoutConfig: { columns: this.items.length },
                    defaults: this.defaults,
                    items: this.items
                });
                for (var i = 0, len = this.items.length; i < len; i++) {
                    Ext.applyIf(this.items[i], colCfg);
                }

            } else {




                var numCols, cols = [];

                if (typeof this.columns == 'string') {
                    this.columns = this.items.length;
                }
                if (!Ext.isArray(this.columns)) {
                    var cs = [];
                    for (var i = 0; i < this.columns; i++) {
                        cs.push((100 / this.columns) * .01);
                    }
                    this.columns = cs;
                }

                numCols = this.columns.length;


                for (var i = 0; i < numCols; i++) {
                    var cc = Ext.apply({ items: [] }, colCfg);
                    cc[this.columns[i] <= 1 ? 'columnWidth' : 'width'] = this.columns[i];
                    if (this.defaults) {
                        cc.defaults = Ext.apply(cc.defaults || {}, this.defaults);
                    }
                    cols.push(cc);
                };


                if (this.vertical) {
                    var rows = Math.ceil(this.items.length / numCols), ri = 0;
                    for (var i = 0, len = this.items.length; i < len; i++) {
                        if (i > 0 && i % rows == 0) {
                            ri++;
                        }
                        if (this.items[i].fieldLabel) {
                            this.items[i].hideLabel = false;
                        }
                        cols[ri].items.push(this.items[i]);
                    };
                } else {
                    for (var i = 0, len = this.items.length; i < len; i++) {
                        var ci = i % numCols;
                        if (this.items[i].fieldLabel) {
                            this.items[i].hideLabel = false;
                        }
                        cols[ci].items.push(this.items[i]);
                    };
                }

                Ext.apply(panelCfg, {
                    layoutConfig: { columns: numCols },
                    items: cols
                });
            }

            this.panel = new Ext.Container(panelCfg);
            this.panel.ownerCt = this;
            this.el = this.panel.getEl();

            if (this.forId && this.itemCls) {
                var l = this.el.up(this.itemCls).child('label', true);
                if (l) {
                    l.setAttribute('htmlFor', this.forId);
                }
            }

            var fields = this.panel.findBy(function (c) {
                return c.isFormField;
            }, this);

            this.items = new Ext.util.MixedCollection();
            this.items.addAll(fields);
        }
        Ext.form.CheckboxGroup.superclass.onRender.call(this, ct, position);
    },

    initValue: function () {
        if (this.value) {
            this.setValue.apply(this, this.buffered ? this.value : [this.value]);
            delete this.buffered;
            delete this.value;
        }
    },

    afterRender: function () {
        Ext.form.CheckboxGroup.superclass.afterRender.call(this);
        this.eachItem(function (item) {
            item.on('check', this.fireChecked, this);
            item.inGroup = true;
        });
    },


    doLayout: function () {

        if (this.rendered) {
            this.panel.forceLayout = this.ownerCt.forceLayout;
            this.panel.doLayout();
        }
    },


    fireChecked: function () {
        var arr = [];
        this.eachItem(function (item) {
            if (item.checked) {
                arr.push(item);
            }
        });
        this.fireEvent('change', this, arr);
    },


    getErrors: function () {
        var errors = Ext.form.CheckboxGroup.superclass.getErrors.apply(this, arguments);

        if (!this.allowBlank) {
            var blank = true;

            this.eachItem(function (f) {
                if (f.checked) {
                    return (blank = false);
                }
            });

            if (blank) errors.push(this.blankText);
        }

        return errors;
    },


    isDirty: function () {

        if (this.disabled || !this.rendered) {
            return false;
        }

        var dirty = false;

        this.eachItem(function (item) {
            if (item.isDirty()) {
                dirty = true;
                return false;
            }
        });

        return dirty;
    },


    setReadOnly: function (readOnly) {
        if (this.rendered) {
            this.eachItem(function (item) {
                item.setReadOnly(readOnly);
            });
        }
        this.readOnly = readOnly;
    },


    onDisable: function () {
        this.eachItem(function (item) {
            item.disable();
        });
    },


    onEnable: function () {
        this.eachItem(function (item) {
            item.enable();
        });
    },


    onResize: function (w, h) {
        this.panel.setSize(w, h);
        this.panel.doLayout();
    },


    reset: function () {
        if (this.originalValue) {

            this.eachItem(function (c) {
                if (c.setValue) {
                    c.setValue(false);
                    c.originalValue = c.getValue();
                }
            });


            this.resetOriginal = true;
            this.setValue(this.originalValue);
            delete this.resetOriginal;
        } else {
            this.eachItem(function (c) {
                if (c.reset) {
                    c.reset();
                }
            });
        }


        (function () {
            this.clearInvalid();
        }).defer(50, this);
    },


    setValue: function () {
        if (this.rendered) {
            this.onSetValue.apply(this, arguments);
        } else {
            this.buffered = true;
            this.value = arguments;
        }
        return this;
    },


    onSetValue: function (id, value) {
        if (arguments.length == 1) {
            if (Ext.isArray(id)) {
                Ext.each(id, function (val, idx) {
                    if (Ext.isObject(val) && val.setValue) {
                        val.setValue(true);
                        if (this.resetOriginal === true) {
                            val.originalValue = val.getValue();
                        }
                    } else {
                        var item = this.items.itemAt(idx);
                        if (item) {
                            item.setValue(val);
                        }
                    }
                }, this);
            } else if (Ext.isObject(id)) {

                for (var i in id) {
                    var f = this.getBox(i);
                    if (f) {
                        f.setValue(id[i]);
                    }
                }
            } else {
                this.setValueForItem(id);
            }
        } else {
            var f = this.getBox(id);
            if (f) {
                f.setValue(value);
            }
        }
    },


    beforeDestroy: function () {
        Ext.destroy(this.panel);
        if (!this.rendered) {
            Ext.destroy(this.items);
        }
        Ext.form.CheckboxGroup.superclass.beforeDestroy.call(this);

    },

    setValueForItem: function (val) {
        val = String(val).split(',');
        this.eachItem(function (item) {
            if (val.indexOf(item.inputValue) > -1) {
                item.setValue(true);
            }
        });
    },


    getBox: function (id) {
        var box = null;
        this.eachItem(function (f) {
            if (id == f || f.dataIndex == id || f.id == id || f.getName() == id) {
                box = f;
                return false;
            }
        });
        return box;
    },


    getValue: function () {
        var out = [];
        this.eachItem(function (item) {
            if (item.checked) {
                out.push(item);
            }
        });
        return out;
    },


    eachItem: function (fn, scope) {
        if (this.items && this.items.each) {
            this.items.each(fn, scope || this);
        }
    },




    getRawValue: Ext.emptyFn,


    setRawValue: Ext.emptyFn

});

Ext.reg('checkboxgroup', Ext.form.CheckboxGroup);

Ext.form.CompositeField = Ext.extend(Ext.form.Field, {


    defaultMargins: '0 5 0 0',


    skipLastItemMargin: true,


    isComposite: true,


    combineErrors: true,


    labelConnector: ', ',





    initComponent: function () {
        var labels = [],
            items = this.items,
            item;

        for (var i = 0, j = items.length; i < j; i++) {
            item = items[i];

            labels.push(item.fieldLabel);


            Ext.applyIf(item, this.defaults);


            if (!(i == j - 1 && this.skipLastItemMargin)) {
                Ext.applyIf(item, { margins: this.defaultMargins });
            }
        }

        this.fieldLabel = this.fieldLabel || this.buildLabel(labels);


        this.fieldErrors = new Ext.util.MixedCollection(true, function (item) {
            return item.field;
        });

        this.fieldErrors.on({
            scope: this,
            add: this.updateInvalidMark,
            remove: this.updateInvalidMark,
            replace: this.updateInvalidMark
        });

        Ext.form.CompositeField.superclass.initComponent.apply(this, arguments);

        this.innerCt = new Ext.Container({
            layout: 'hbox',
            items: this.items,
            cls: 'x-form-composite',
            defaultMargins: '0 3 0 0'
        });

        var fields = this.innerCt.findBy(function (c) {
            return c.isFormField;
        }, this);


        this.items = new Ext.util.MixedCollection();
        this.items.addAll(fields);

    },


    onRender: function (ct, position) {
        if (!this.el) {

            var innerCt = this.innerCt;
            innerCt.render(ct);

            this.el = innerCt.getEl();



            if (this.combineErrors) {
                this.eachItem(function (field) {
                    Ext.apply(field, {
                        markInvalid: this.onFieldMarkInvalid.createDelegate(this, [field], 0),
                        clearInvalid: this.onFieldClearInvalid.createDelegate(this, [field], 0)
                    });
                });
            }


            var l = this.el.parent().parent().child('label', true);
            if (l) {
                l.setAttribute('for', this.items.items[0].id);
            }
        }

        Ext.form.CompositeField.superclass.onRender.apply(this, arguments);
    },


    onFieldMarkInvalid: function (field, message) {
        var name = field.getName(),
            error = {
                field: name,
                errorName: field.fieldLabel || name,
                error: message
            };

        this.fieldErrors.replace(name, error);

        field.el.addClass(field.invalidClass);
    },


    onFieldClearInvalid: function (field) {
        this.fieldErrors.removeKey(field.getName());

        field.el.removeClass(field.invalidClass);
    },


    updateInvalidMark: function () {
        var ieStrict = Ext.isIE6 && Ext.isStrict;

        if (this.fieldErrors.length == 0) {
            this.clearInvalid();


            if (ieStrict) {
                this.clearInvalid.defer(50, this);
            }
        } else {
            var message = this.buildCombinedErrorMessage(this.fieldErrors.items);

            this.sortErrors();
            this.markInvalid(message);


            if (ieStrict) {
                this.markInvalid(message);
            }
        }
    },


    validateValue: function () {
        var valid = true;

        this.eachItem(function (field) {
            if (!field.isValid()) valid = false;
        });

        return valid;
    },


    buildCombinedErrorMessage: function (errors) {
        var combined = [],
            error;

        for (var i = 0, j = errors.length; i < j; i++) {
            error = errors[i];

            combined.push(String.format("{0}: {1}", error.errorName, error.error));
        }

        return combined.join("<br />");
    },


    sortErrors: function () {
        var fields = this.items;

        this.fieldErrors.sort("ASC", function (a, b) {
            var findByName = function (key) {
                return function (field) {
                    return field.getName() == key;
                };
            };

            var aIndex = fields.findIndexBy(findByName(a.field)),
                bIndex = fields.findIndexBy(findByName(b.field));

            return aIndex < bIndex ? -1 : 1;
        });
    },


    reset: function () {
        this.eachItem(function (item) {
            item.reset();
        });



        (function () {
            this.clearInvalid();
        }).defer(50, this);
    },


    clearInvalidChildren: function () {
        this.eachItem(function (item) {
            item.clearInvalid();
        });
    },


    buildLabel: function (segments) {
        return Ext.clean(segments).join(this.labelConnector);
    },


    isDirty: function () {

        if (this.disabled || !this.rendered) {
            return false;
        }

        var dirty = false;
        this.eachItem(function (item) {
            if (item.isDirty()) {
                dirty = true;
                return false;
            }
        });
        return dirty;
    },


    eachItem: function (fn, scope) {
        if (this.items && this.items.each) {
            this.items.each(fn, scope || this);
        }
    },


    onResize: function (adjWidth, adjHeight, rawWidth, rawHeight) {
        var innerCt = this.innerCt;

        if (this.rendered && innerCt.rendered) {
            innerCt.setSize(adjWidth, adjHeight);
        }

        Ext.form.CompositeField.superclass.onResize.apply(this, arguments);
    },


    doLayout: function (shallow, force) {
        if (this.rendered) {
            var innerCt = this.innerCt;

            innerCt.forceLayout = this.ownerCt.forceLayout;
            innerCt.doLayout(shallow, force);
        }
    },


    beforeDestroy: function () {
        Ext.destroy(this.innerCt);

        Ext.form.CompositeField.superclass.beforeDestroy.call(this);
    },


    setReadOnly: function (readOnly) {
        if (readOnly == undefined) {
            readOnly = true;
        }
        readOnly = !!readOnly;

        if (this.rendered) {
            this.eachItem(function (item) {
                item.setReadOnly(readOnly);
            });
        }
        this.readOnly = readOnly;
    },

    onShow: function () {
        Ext.form.CompositeField.superclass.onShow.call(this);
        this.doLayout();
    },


    onDisable: function () {
        this.eachItem(function (item) {
            item.disable();
        });
    },


    onEnable: function () {
        this.eachItem(function (item) {
            item.enable();
        });
    }
});

Ext.reg('compositefield', Ext.form.CompositeField);
Ext.form.Radio = Ext.extend(Ext.form.Checkbox, {
    inputType: 'radio',


    markInvalid: Ext.emptyFn,

    clearInvalid: Ext.emptyFn,


    getGroupValue: function () {
        var p = this.el.up('form') || Ext.getBody();
        var c = p.child('input[name=' + this.el.dom.name + ']:checked', true);
        return c ? c.value : null;
    },


    setValue: function (v) {
        var checkEl,
            els,
            radio;
        if (typeof v == 'boolean') {
            Ext.form.Radio.superclass.setValue.call(this, v);
        } else if (this.rendered) {
            checkEl = this.getCheckEl();
            radio = checkEl.child('input[name=' + this.el.dom.name + '][value=' + v + ']', true);
            if (radio) {
                Ext.getCmp(radio.id).setValue(true);
            }
        }
        if (this.rendered && this.checked) {
            checkEl = checkEl || this.getCheckEl();
            els = this.getCheckEl().select('input[name=' + this.el.dom.name + ']');
            els.each(function (el) {
                if (el.dom.id != this.id) {
                    Ext.getCmp(el.dom.id).setValue(false);
                }
            }, this);
        }
        return this;
    },


    getCheckEl: function () {
        if (this.inGroup) {
            return this.el.up('.x-form-radio-group');
        }
        return this.el.up('form') || Ext.getBody();
    }
});
Ext.reg('radio', Ext.form.Radio);

Ext.form.RadioGroup = Ext.extend(Ext.form.CheckboxGroup, {


    allowBlank: true,

    blankText: 'You must select one item in this group',


    defaultType: 'radio',


    groupCls: 'x-form-radio-group',




    getValue: function () {
        var out = null;
        this.eachItem(function (item) {
            if (item.checked) {
                out = item;
                return false;
            }
        });
        return out;
    },


    onSetValue: function (id, value) {
        if (arguments.length > 1) {
            var f = this.getBox(id);
            if (f) {
                f.setValue(value);
                if (f.checked) {
                    this.eachItem(function (item) {
                        if (item !== f) {
                            item.setValue(false);
                        }
                    });
                }
            }
        } else {
            this.setValueForItem(id);
        }
    },

    setValueForItem: function (val) {
        val = String(val).split(',')[0];
        this.eachItem(function (item) {
            item.setValue(val == item.inputValue);
        });
    },


    fireChecked: function () {
        if (!this.checkTask) {
            this.checkTask = new Ext.util.DelayedTask(this.bufferChecked, this);
        }
        this.checkTask.delay(10);
    },


    bufferChecked: function () {
        var out = null;
        this.eachItem(function (item) {
            if (item.checked) {
                out = item;
                return false;
            }
        });
        this.fireEvent('change', this, out);
    },

    onDestroy: function () {
        if (this.checkTask) {
            this.checkTask.cancel();
            this.checkTask = null;
        }
        Ext.form.RadioGroup.superclass.onDestroy.call(this);
    }

});

Ext.reg('radiogroup', Ext.form.RadioGroup);

Ext.form.Hidden = Ext.extend(Ext.form.Field, {

    inputType: 'hidden',

    shouldLayout: false,


    onRender: function () {
        Ext.form.Hidden.superclass.onRender.apply(this, arguments);
    },


    initEvents: function () {
        this.originalValue = this.getValue();
    },


    setSize: Ext.emptyFn,
    setWidth: Ext.emptyFn,
    setHeight: Ext.emptyFn,
    setPosition: Ext.emptyFn,
    setPagePosition: Ext.emptyFn,
    markInvalid: Ext.emptyFn,
    clearInvalid: Ext.emptyFn
});
Ext.reg('hidden', Ext.form.Hidden);
Ext.form.BasicForm = Ext.extend(Ext.util.Observable, {

    constructor: function (el, config) {
        Ext.apply(this, config);
        if (Ext.isString(this.paramOrder)) {
            this.paramOrder = this.paramOrder.split(/[\s,|]/);
        }

        this.items = new Ext.util.MixedCollection(false, function (o) {
            return o.getItemId();
        });
        this.addEvents(

            'beforeaction',

            'actionfailed',

            'actioncomplete'
        );

        if (el) {
            this.initEl(el);
        }
        Ext.form.BasicForm.superclass.constructor.call(this);
    },








    timeout: 30,




    paramOrder: undefined,


    paramsAsHash: false,


    waitTitle: 'Please Wait...',


    activeAction: null,


    trackResetOnLoad: false,





    initEl: function (el) {
        this.el = Ext.get(el);
        this.id = this.el.id || Ext.id();
        if (!this.standardSubmit) {
            this.el.on('submit', this.onSubmit, this);
        }
        this.el.addClass('x-form');
    },


    getEl: function () {
        return this.el;
    },


    onSubmit: function (e) {
        e.stopEvent();
    },


    destroy: function (bound) {
        if (bound !== true) {
            this.items.each(function (f) {
                Ext.destroy(f);
            });
            Ext.destroy(this.el);
        }
        this.items.clear();
        this.purgeListeners();
    },


    isValid: function () {
        var valid = true;
        this.items.each(function (f) {
            if (!f.validate()) {
                valid = false;
            }
        });
        return valid;
    },


    isDirty: function () {
        var dirty = false;
        this.items.each(function (f) {
            if (f.isDirty()) {
                dirty = true;
                return false;
            }
        });
        return dirty;
    },


    doAction: function (action, options) {
        if (Ext.isString(action)) {
            action = new Ext.form.Action.ACTION_TYPES[action](this, options);
        }
        if (this.fireEvent('beforeaction', this, action) !== false) {
            this.beforeAction(action);
            action.run.defer(100, action);
        }
        return this;
    },


    submit: function (options) {
        options = options || {};
        if (this.standardSubmit) {
            var v = options.clientValidation === false || this.isValid();
            if (v) {
                var el = this.el.dom;
                if (this.url && Ext.isEmpty(el.action)) {
                    el.action = this.url;
                }
                el.submit();
            }
            return v;
        }
        var submitAction = String.format('{0}submit', this.api ? 'direct' : '');
        this.doAction(submitAction, options);
        return this;
    },


    load: function (options) {
        var loadAction = String.format('{0}load', this.api ? 'direct' : '');
        this.doAction(loadAction, options);
        return this;
    },


    updateRecord: function (record) {
        record.beginEdit();
        var fs = record.fields;
        fs.each(function (f) {
            var field = this.findField(f.name);
            if (field) {
                var value = field.getValue();
                if (value.getGroupValue) {
                    value = value.getGroupValue();
                } else if (field.eachItem) {
                    value = [];
                    field.eachItem(function (item) {
                        value.push(item.getValue());
                    });
                }
                record.set(f.name, value);
            }
        }, this);
        record.endEdit();
        return this;
    },


    loadRecord: function (record) {
        this.setValues(record.data);
        return this;
    },


    beforeAction: function (action) {

        this.items.each(function (f) {
            if (f.isFormField && f.syncValue) {
                f.syncValue();
            }
        });
        var o = action.options;
        if (o.waitMsg) {
            if (this.waitMsgTarget === true) {
                this.el.mask(o.waitMsg, 'x-mask-loading');
            } else if (this.waitMsgTarget) {
                this.waitMsgTarget = Ext.get(this.waitMsgTarget);
                this.waitMsgTarget.mask(o.waitMsg, 'x-mask-loading');
            } else {
                Ext.MessageBox.wait(o.waitMsg, o.waitTitle || this.waitTitle);
            }
        }
    },


    afterAction: function (action, success) {
        this.activeAction = null;
        var o = action.options;
        if (o.waitMsg) {
            if (this.waitMsgTarget === true) {
                this.el.unmask();
            } else if (this.waitMsgTarget) {
                this.waitMsgTarget.unmask();
            } else {
                Ext.MessageBox.updateProgress(1);
                Ext.MessageBox.hide();
            }
        }
        if (success) {
            if (o.reset) {
                this.reset();
            }
            Ext.callback(o.success, o.scope, [this, action]);
            this.fireEvent('actioncomplete', this, action);
        } else {
            Ext.callback(o.failure, o.scope, [this, action]);
            this.fireEvent('actionfailed', this, action);
        }
    },


    findField: function (id) {
        var field = this.items.get(id);

        if (!Ext.isObject(field)) {

            var findMatchingField = function (f) {
                if (f.isFormField) {
                    if (f.dataIndex == id || f.id == id || f.getName() == id) {
                        field = f;
                        return false;
                    } else if (f.isComposite) {
                        return f.items.each(findMatchingField);
                    } else if (f instanceof Ext.form.CheckboxGroup && f.rendered) {
                        return f.eachItem(findMatchingField);
                    }
                }
            };

            this.items.each(findMatchingField);
        }
        return field || null;
    },



    markInvalid: function (errors) {
        if (Ext.isArray(errors)) {
            for (var i = 0, len = errors.length; i < len; i++) {
                var fieldError = errors[i];
                var f = this.findField(fieldError.id);
                if (f) {
                    f.markInvalid(fieldError.msg);
                }
            }
        } else {
            var field, id;
            for (id in errors) {
                if (!Ext.isFunction(errors[id]) && (field = this.findField(id))) {
                    field.markInvalid(errors[id]);
                }
            }
        }

        return this;
    },


    setValues: function (values) {
        if (Ext.isArray(values)) {
            for (var i = 0, len = values.length; i < len; i++) {
                var v = values[i];
                var f = this.findField(v.id);
                if (f) {
                    f.setValue(v.value);
                    if (this.trackResetOnLoad) {
                        f.originalValue = f.getValue();
                    }
                }
            }
        } else {
            var field, id;
            for (id in values) {
                if (!Ext.isFunction(values[id]) && (field = this.findField(id))) {
                    field.setValue(values[id]);
                    if (this.trackResetOnLoad) {
                        field.originalValue = field.getValue();
                    }
                }
            }
        }
        return this;
    },


    getValues: function (asString) {
        var fs = Ext.lib.Ajax.serializeForm(this.el.dom);
        if (asString === true) {
            return fs;
        }
        return Ext.urlDecode(fs);
    },


    getFieldValues: function (dirtyOnly) {
        var o = {},
            n,
            key,
            val;
        this.items.each(function (f) {
            if (!f.disabled && (dirtyOnly !== true || f.isDirty())) {
                n = f.getName();
                key = o[n];
                val = f.getValue();

                if (Ext.isDefined(key)) {
                    if (Ext.isArray(key)) {
                        o[n].push(val);
                    } else {
                        o[n] = [key, val];
                    }
                } else {
                    o[n] = val;
                }
            }
        });
        return o;
    },


    clearInvalid: function () {
        this.items.each(function (f) {
            f.clearInvalid();
        });
        return this;
    },


    reset: function () {
        this.items.each(function (f) {
            f.reset();
        });
        return this;
    },


    add: function () {
        this.items.addAll(Array.prototype.slice.call(arguments, 0));
        return this;
    },


    remove: function (field) {
        this.items.remove(field);
        return this;
    },


    cleanDestroyed: function () {
        this.items.filterBy(function (o) { return !!o.isDestroyed; }).each(this.remove, this);
    },


    render: function () {
        this.items.each(function (f) {
            if (f.isFormField && !f.rendered && document.getElementById(f.id)) {
                f.applyToMarkup(f.id);
            }
        });
        return this;
    },


    applyToFields: function (o) {
        this.items.each(function (f) {
            Ext.apply(f, o);
        });
        return this;
    },


    applyIfToFields: function (o) {
        this.items.each(function (f) {
            Ext.applyIf(f, o);
        });
        return this;
    },

    callFieldMethod: function (fnName, args) {
        args = args || [];
        this.items.each(function (f) {
            if (Ext.isFunction(f[fnName])) {
                f[fnName].apply(f, args);
            }
        });
        return this;
    }
});


Ext.BasicForm = Ext.form.BasicForm;

Ext.FormPanel = Ext.extend(Ext.Panel, {










    minButtonWidth: 75,


    labelAlign: 'left',


    monitorValid: false,


    monitorPoll: 200,


    layout: 'form',


    initComponent: function () {
        this.form = this.createForm();
        Ext.FormPanel.superclass.initComponent.call(this);

        this.bodyCfg = {
            tag: 'form',
            cls: this.baseCls + '-body',
            method: this.method || 'POST',
            id: this.formId || Ext.id()
        };
        if (this.fileUpload) {
            this.bodyCfg.enctype = 'multipart/form-data';
        }
        this.initItems();

        this.addEvents(

            'clientvalidation'
        );

        this.relayEvents(this.form, ['beforeaction', 'actionfailed', 'actioncomplete']);
    },


    createForm: function () {
        var config = Ext.applyIf({ listeners: {} }, this.initialConfig);
        return new Ext.form.BasicForm(null, config);
    },


    initFields: function () {
        var f = this.form;
        var formPanel = this;
        var fn = function (c) {
            if (formPanel.isField(c)) {
                f.add(c);
            } else if (c.findBy && c != formPanel) {
                formPanel.applySettings(c);

                if (c.items && c.items.each) {
                    c.items.each(fn, this);
                }
            }
        };
        this.items.each(fn, this);
    },


    applySettings: function (c) {
        var ct = c.ownerCt;
        Ext.applyIf(c, {
            labelAlign: ct.labelAlign,
            labelWidth: ct.labelWidth,
            itemCls: ct.itemCls
        });
    },


    getLayoutTarget: function () {
        return this.form.el;
    },


    getForm: function () {
        return this.form;
    },


    onRender: function (ct, position) {
        this.initFields();
        Ext.FormPanel.superclass.onRender.call(this, ct, position);
        this.form.initEl(this.body);
    },


    beforeDestroy: function () {
        this.stopMonitoring();
        this.form.destroy(true);
        Ext.FormPanel.superclass.beforeDestroy.call(this);
    },


    isField: function (c) {
        return !!c.setValue && !!c.getValue && !!c.markInvalid && !!c.clearInvalid;
    },


    initEvents: function () {
        Ext.FormPanel.superclass.initEvents.call(this);

        this.on({
            scope: this,
            add: this.onAddEvent,
            remove: this.onRemoveEvent
        });
        if (this.monitorValid) {
            this.startMonitoring();
        }
    },


    onAdd: function (c) {
        Ext.FormPanel.superclass.onAdd.call(this, c);
        this.processAdd(c);
    },


    onAddEvent: function (ct, c) {
        if (ct !== this) {
            this.processAdd(c);
        }
    },


    processAdd: function (c) {

        if (this.isField(c)) {
            this.form.add(c);

        } else if (c.findBy) {
            this.applySettings(c);
            this.form.add.apply(this.form, c.findBy(this.isField));
        }
    },


    onRemove: function (c) {
        Ext.FormPanel.superclass.onRemove.call(this, c);
        this.processRemove(c);
    },

    onRemoveEvent: function (ct, c) {
        if (ct !== this) {
            this.processRemove(c);
        }
    },


    processRemove: function (c) {
        if (!this.destroying) {

            if (this.isField(c)) {
                this.form.remove(c);

            } else if (c.findBy) {
                Ext.each(c.findBy(this.isField), this.form.remove, this.form);

                this.form.cleanDestroyed();
            }
        }
    },


    startMonitoring: function () {
        if (!this.validTask) {
            this.validTask = new Ext.util.TaskRunner();
            this.validTask.start({
                run: this.bindHandler,
                interval: this.monitorPoll || 200,
                scope: this
            });
        }
    },


    stopMonitoring: function () {
        if (this.validTask) {
            this.validTask.stopAll();
            this.validTask = null;
        }
    },


    load: function () {
        this.form.load.apply(this.form, arguments);
    },


    onDisable: function () {
        Ext.FormPanel.superclass.onDisable.call(this);
        if (this.form) {
            this.form.items.each(function () {
                this.disable();
            });
        }
    },


    onEnable: function () {
        Ext.FormPanel.superclass.onEnable.call(this);
        if (this.form) {
            this.form.items.each(function () {
                this.enable();
            });
        }
    },


    bindHandler: function () {
        var valid = true;
        this.form.items.each(function (f) {
            if (!f.isValid(true)) {
                valid = false;
                return false;
            }
        });
        if (this.fbar) {
            var fitems = this.fbar.items.items;
            for (var i = 0, len = fitems.length; i < len; i++) {
                var btn = fitems[i];
                if (btn.formBind === true && btn.disabled === valid) {
                    btn.setDisabled(!valid);
                }
            }
        }
        this.fireEvent('clientvalidation', this, valid);
    }
});
Ext.reg('form', Ext.FormPanel);

Ext.form.FormPanel = Ext.FormPanel;

Ext.form.FieldSet = Ext.extend(Ext.Panel, {






    baseCls: 'x-fieldset',

    layout: 'form',

    animCollapse: false,


    onRender: function (ct, position) {
        if (!this.el) {
            this.el = document.createElement('fieldset');
            this.el.id = this.id;
            if (this.title || this.header || this.checkboxToggle) {
                this.el.appendChild(document.createElement('legend')).className = this.baseCls + '-header';
            }
        }

        Ext.form.FieldSet.superclass.onRender.call(this, ct, position);

        if (this.checkboxToggle) {
            var o = typeof this.checkboxToggle == 'object' ?
                    this.checkboxToggle :
                    { tag: 'input', type: 'checkbox', name: this.checkboxName || this.id + '-checkbox' };
            this.checkbox = this.header.insertFirst(o);
            this.checkbox.dom.checked = !this.collapsed;
            this.mon(this.checkbox, 'click', this.onCheckClick, this);
        }
    },


    onCollapse: function (doAnim, animArg) {
        if (this.checkbox) {
            this.checkbox.dom.checked = false;
        }
        Ext.form.FieldSet.superclass.onCollapse.call(this, doAnim, animArg);

    },


    onExpand: function (doAnim, animArg) {
        if (this.checkbox) {
            this.checkbox.dom.checked = true;
        }
        Ext.form.FieldSet.superclass.onExpand.call(this, doAnim, animArg);
    },


    onCheckClick: function () {
        this[this.checkbox.dom.checked ? 'expand' : 'collapse']();
    }



































});
Ext.reg('fieldset', Ext.form.FieldSet);

Ext.form.HtmlEditor = Ext.extend(Ext.form.Field, {

    enableFormat: true,

    enableFontSize: true,

    enableColors: true,

    enableAlignments: true,

    enableLists: true,

    enableSourceEdit: true,

    enableLinks: true,

    enableFont: true,

    createLinkText: 'Please enter the URL for the link:',

    defaultLinkValue: 'http:/' + '/',

    fontFamilies: [
        'Arial',
        'Courier New',
        'Tahoma',
        'Times New Roman',
        'Verdana'
    ],
    defaultFont: 'tahoma',

    defaultValue: (Ext.isOpera || Ext.isIE6) ? '&#160;' : '&#8203;',


    actionMode: 'wrap',
    validationEvent: false,
    deferHeight: true,
    initialized: false,
    activated: false,
    sourceEditMode: false,
    onFocus: Ext.emptyFn,
    iframePad: 3,
    hideMode: 'offsets',
    defaultAutoCreate: {
        tag: "textarea",
        style: "width:500px;height:300px;",
        autocomplete: "off"
    },


    initComponent: function () {
        this.addEvents(

            'initialize',

            'activate',

            'beforesync',

            'beforepush',

            'sync',

            'push',

            'editmodechange'
        );
        Ext.form.HtmlEditor.superclass.initComponent.call(this);
    },


    createFontOptions: function () {
        var buf = [], fs = this.fontFamilies, ff, lc;
        for (var i = 0, len = fs.length; i < len; i++) {
            ff = fs[i];
            lc = ff.toLowerCase();
            buf.push(
                '<option value="', lc, '" style="font-family:', ff, ';"',
                    (this.defaultFont == lc ? ' selected="true">' : '>'),
                    ff,
                '</option>'
            );
        }
        return buf.join('');
    },


    createToolbar: function (editor) {
        var items = [];
        var tipsEnabled = Ext.QuickTips && Ext.QuickTips.isEnabled();


        function btn(id, toggle, handler) {
            return {
                itemId: id,
                cls: 'x-btn-icon',
                iconCls: 'x-edit-' + id,
                enableToggle: toggle !== false,
                scope: editor,
                handler: handler || editor.relayBtnCmd,
                clickEvent: 'mousedown',
                tooltip: tipsEnabled ? editor.buttonTips[id] || undefined : undefined,
                overflowText: editor.buttonTips[id].title || undefined,
                tabIndex: -1
            };
        }


        if (this.enableFont && !Ext.isSafari2) {
            var fontSelectItem = new Ext.Toolbar.Item({
                autoEl: {
                    tag: 'select',
                    cls: 'x-font-select',
                    html: this.createFontOptions()
                }
            });

            items.push(
                fontSelectItem,
                '-'
            );
        }

        if (this.enableFormat) {
            items.push(
                btn('bold'),
                btn('italic'),
                btn('underline')
            );
        }

        if (this.enableFontSize) {
            items.push(
                '-',
                btn('increasefontsize', false, this.adjustFont),
                btn('decreasefontsize', false, this.adjustFont)
            );
        }

        if (this.enableColors) {
            items.push(
                '-', {
                    itemId: 'forecolor',
                    cls: 'x-btn-icon',
                    iconCls: 'x-edit-forecolor',
                    clickEvent: 'mousedown',
                    tooltip: tipsEnabled ? editor.buttonTips.forecolor || undefined : undefined,
                    tabIndex: -1,
                    menu: new Ext.menu.ColorMenu({
                        allowReselect: true,
                        focus: Ext.emptyFn,
                        value: '000000',
                        plain: true,
                        listeners: {
                            scope: this,
                            select: function (cp, color) {
                                this.execCmd('forecolor', Ext.isWebKit || Ext.isIE ? '#' + color : color);
                                this.deferFocus();
                            }
                        },
                        clickEvent: 'mousedown'
                    })
                }, {
                    itemId: 'backcolor',
                    cls: 'x-btn-icon',
                    iconCls: 'x-edit-backcolor',
                    clickEvent: 'mousedown',
                    tooltip: tipsEnabled ? editor.buttonTips.backcolor || undefined : undefined,
                    tabIndex: -1,
                    menu: new Ext.menu.ColorMenu({
                        focus: Ext.emptyFn,
                        value: 'FFFFFF',
                        plain: true,
                        allowReselect: true,
                        listeners: {
                            scope: this,
                            select: function (cp, color) {
                                if (Ext.isGecko) {
                                    this.execCmd('useCSS', false);
                                    this.execCmd('hilitecolor', color);
                                    this.execCmd('useCSS', true);
                                    this.deferFocus();
                                } else {
                                    this.execCmd(Ext.isOpera ? 'hilitecolor' : 'backcolor', Ext.isWebKit || Ext.isIE ? '#' + color : color);
                                    this.deferFocus();
                                }
                            }
                        },
                        clickEvent: 'mousedown'
                    })
                }
            );
        }

        if (this.enableAlignments) {
            items.push(
                '-',
                btn('justifyleft'),
                btn('justifycenter'),
                btn('justifyright')
            );
        }

        if (!Ext.isSafari2) {
            if (this.enableLinks) {
                items.push(
                    '-',
                    btn('createlink', false, this.createLink)
                );
            }

            if (this.enableLists) {
                items.push(
                    '-',
                    btn('insertorderedlist'),
                    btn('insertunorderedlist')
                );
            }
            if (this.enableSourceEdit) {
                items.push(
                    '-',
                    btn('sourceedit', true, function (btn) {
                        this.toggleSourceEdit(!this.sourceEditMode);
                    })
                );
            }
        }


        var tb = new Ext.Toolbar({
            renderTo: this.wrap.dom.firstChild,
            items: items
        });

        if (fontSelectItem) {
            this.fontSelect = fontSelectItem.el;

            this.mon(this.fontSelect, 'change', function () {
                var font = this.fontSelect.dom.value;
                this.relayCmd('fontname', font);
                this.deferFocus();
            }, this);
        }


        this.mon(tb.el, 'click', function (e) {
            e.preventDefault();
        });

        this.tb = tb;
        this.tb.doLayout();
    },

    onDisable: function () {
        this.wrap.mask();
        Ext.form.HtmlEditor.superclass.onDisable.call(this);
    },

    onEnable: function () {
        this.wrap.unmask();
        Ext.form.HtmlEditor.superclass.onEnable.call(this);
    },

    setReadOnly: function (readOnly) {

        Ext.form.HtmlEditor.superclass.setReadOnly.call(this, readOnly);
        if (this.initialized) {
            if (Ext.isIE) {
                this.getEditorBody().contentEditable = !readOnly;
            } else {
                this.setDesignMode(!readOnly);
            }
            var bd = this.getEditorBody();
            if (bd) {
                bd.style.cursor = this.readOnly ? 'default' : 'text';
            }
            this.disableItems(readOnly);
        }
    },


    getDocMarkup: function () {
        var h = Ext.fly(this.iframe).getHeight() - this.iframePad * 2;
        return String.format('<html><head><style type="text/css">body{border: 0; margin: 0; padding: {0}px; height: {1}px; cursor: text}</style></head><body></body></html>', this.iframePad, h);
    },


    getEditorBody: function () {
        var doc = this.getDoc();
        return doc.body || doc.documentElement;
    },


    getDoc: function () {
        return Ext.isIE ? this.getWin().document : (this.iframe.contentDocument || this.getWin().document);
    },


    getWin: function () {
        return Ext.isIE ? this.iframe.contentWindow : window.frames[this.iframe.name];
    },


    onRender: function (ct, position) {
        Ext.form.HtmlEditor.superclass.onRender.call(this, ct, position);
        this.el.dom.style.border = '0 none';
        this.el.dom.setAttribute('tabIndex', -1);
        this.el.addClass('x-hidden');
        if (Ext.isIE) {
            this.el.applyStyles('margin-top:-1px;margin-bottom:-1px;');
        }
        this.wrap = this.el.wrap({
            cls: 'x-html-editor-wrap', cn: { cls: 'x-html-editor-tb' }
        });

        this.createToolbar(this);

        this.disableItems(true);

        this.tb.doLayout();

        this.createIFrame();

        if (!this.width) {
            var sz = this.el.getSize();
            this.setSize(sz.width, this.height || sz.height);
        }
        this.resizeEl = this.positionEl = this.wrap;
    },

    createIFrame: function () {
        var iframe = document.createElement('iframe');
        iframe.name = Ext.id();
        iframe.frameBorder = '0';
        iframe.style.overflow = 'auto';
        iframe.src = Ext.SSL_SECURE_URL;

        this.wrap.dom.appendChild(iframe);
        this.iframe = iframe;

        this.monitorTask = Ext.TaskMgr.start({
            run: this.checkDesignMode,
            scope: this,
            interval: 100
        });
    },

    initFrame: function () {
        Ext.TaskMgr.stop(this.monitorTask);
        var doc = this.getDoc();
        this.win = this.getWin();

        doc.open();
        doc.write(this.getDocMarkup());
        doc.close();

        var task = {
            run: function () {
                var doc = this.getDoc();
                if (doc.body || doc.readyState == 'complete') {
                    Ext.TaskMgr.stop(task);
                    this.setDesignMode(true);
                    this.initEditor.defer(10, this);
                }
            },
            interval: 10,
            duration: 10000,
            scope: this
        };
        Ext.TaskMgr.start(task);
    },


    checkDesignMode: function () {
        if (this.wrap && this.wrap.dom.offsetWidth) {
            var doc = this.getDoc();
            if (!doc) {
                return;
            }
            if (!doc.editorInitialized || this.getDesignMode() != 'on') {
                this.initFrame();
            }
        }
    },


    setDesignMode: function (mode) {
        var doc = this.getDoc();
        if (doc) {
            if (this.readOnly) {
                mode = false;
            }
            doc.designMode = (/on|true/i).test(String(mode).toLowerCase()) ? 'on' : 'off';
        }

    },


    getDesignMode: function () {
        var doc = this.getDoc();
        if (!doc) { return ''; }
        return String(doc.designMode).toLowerCase();

    },

    disableItems: function (disabled) {
        if (this.fontSelect) {
            this.fontSelect.dom.disabled = disabled;
        }
        this.tb.items.each(function (item) {
            if (item.getItemId() != 'sourceedit') {
                item.setDisabled(disabled);
            }
        });
    },


    onResize: function (w, h) {
        Ext.form.HtmlEditor.superclass.onResize.apply(this, arguments);
        if (this.el && this.iframe) {
            if (Ext.isNumber(w)) {
                var aw = w - this.wrap.getFrameWidth('lr');
                this.el.setWidth(aw);
                this.tb.setWidth(aw);
                this.iframe.style.width = Math.max(aw, 0) + 'px';
            }
            if (Ext.isNumber(h)) {
                var ah = h - this.wrap.getFrameWidth('tb') - this.tb.el.getHeight();
                this.el.setHeight(ah);
                this.iframe.style.height = Math.max(ah, 0) + 'px';
                var bd = this.getEditorBody();
                if (bd) {
                    bd.style.height = Math.max((ah - (this.iframePad * 2)), 0) + 'px';
                }
            }
        }
    },


    toggleSourceEdit: function (sourceEditMode) {
        var iframeHeight,
            elHeight;

        if (sourceEditMode === undefined) {
            sourceEditMode = !this.sourceEditMode;
        }
        this.sourceEditMode = sourceEditMode === true;
        var btn = this.tb.getComponent('sourceedit');

        if (btn.pressed !== this.sourceEditMode) {
            btn.toggle(this.sourceEditMode);
            if (!btn.xtbHidden) {
                return;
            }
        }
        if (this.sourceEditMode) {

            this.previousSize = this.getSize();

            iframeHeight = Ext.get(this.iframe).getHeight();

            this.disableItems(true);
            this.syncValue();
            this.iframe.className = 'x-hidden';
            this.el.removeClass('x-hidden');
            this.el.dom.removeAttribute('tabIndex');
            this.el.focus();
            this.el.dom.style.height = iframeHeight + 'px';
        }
        else {
            elHeight = parseInt(this.el.dom.style.height, 10);
            if (this.initialized) {
                this.disableItems(this.readOnly);
            }
            this.pushValue();
            this.iframe.className = '';
            this.el.addClass('x-hidden');
            this.el.dom.setAttribute('tabIndex', -1);
            this.deferFocus();

            this.setSize(this.previousSize);
            delete this.previousSize;
            this.iframe.style.height = elHeight + 'px';
        }
        this.fireEvent('editmodechange', this, this.sourceEditMode);
    },


    createLink: function () {
        var url = prompt(this.createLinkText, this.defaultLinkValue);
        if (url && url != 'http:/' + '/') {
            this.relayCmd('createlink', url);
        }
    },


    initEvents: function () {
        this.originalValue = this.getValue();
    },


    markInvalid: Ext.emptyFn,


    clearInvalid: Ext.emptyFn,


    setValue: function (v) {
        Ext.form.HtmlEditor.superclass.setValue.call(this, v);
        this.pushValue();
        return this;
    },


    cleanHtml: function (html) {
        html = String(html);
        if (Ext.isWebKit) {
            html = html.replace(/\sclass="(?:Apple-style-span|khtml-block-placeholder)"/gi, '');
        }


        if (html.charCodeAt(0) == this.defaultValue.replace(/\D/g, '')) {
            html = html.substring(1);
        }
        return html;
    },


    syncValue: function () {
        if (this.initialized) {
            var bd = this.getEditorBody();
            var html = bd.innerHTML;
            if (Ext.isWebKit) {
                var bs = bd.getAttribute('style');
                var m = bs.match(/text-align:(.*?);/i);
                if (m && m[1]) {
                    html = '<div style="' + m[0] + '">' + html + '</div>';
                }
            }
            html = this.cleanHtml(html);
            if (this.fireEvent('beforesync', this, html) !== false) {
                this.el.dom.value = html;
                this.fireEvent('sync', this, html);
            }
        }
    },


    getValue: function () {
        this[this.sourceEditMode ? 'pushValue' : 'syncValue']();
        return Ext.form.HtmlEditor.superclass.getValue.call(this);
    },


    pushValue: function () {
        if (this.initialized) {
            var v = this.el.dom.value;
            if (!this.activated && v.length < 1) {
                v = this.defaultValue;
            }
            if (this.fireEvent('beforepush', this, v) !== false) {
                this.getEditorBody().innerHTML = v;
                if (Ext.isGecko) {

                    this.setDesignMode(false);
                    this.setDesignMode(true);
                }
                this.fireEvent('push', this, v);
            }

        }
    },


    deferFocus: function () {
        this.focus.defer(10, this);
    },


    focus: function () {
        if (this.win && !this.sourceEditMode) {
            this.win.focus();
        } else {
            this.el.focus();
        }
    },


    initEditor: function () {

        try {
            var dbody = this.getEditorBody(),
                ss = this.el.getStyles('font-size', 'font-family', 'background-image', 'background-repeat', 'background-color', 'color'),
                doc,
                fn;

            ss['background-attachment'] = 'fixed';
            dbody.bgProperties = 'fixed';

            Ext.DomHelper.applyStyles(dbody, ss);

            doc = this.getDoc();

            if (doc) {
                try {
                    Ext.EventManager.removeAll(doc);
                } catch (e) { }
            }


            fn = this.onEditorEvent.createDelegate(this);
            Ext.EventManager.on(doc, {
                mousedown: fn,
                dblclick: fn,
                click: fn,
                keyup: fn,
                buffer: 100
            });

            if (Ext.isGecko) {
                Ext.EventManager.on(doc, 'keypress', this.applyCommand, this);
            }
            if (Ext.isIE || Ext.isWebKit || Ext.isOpera) {
                Ext.EventManager.on(doc, 'keydown', this.fixKeys, this);
            }
            doc.editorInitialized = true;
            this.initialized = true;
            this.pushValue();
            this.setReadOnly(this.readOnly);
            this.fireEvent('initialize', this);
        } catch (e) { }
    },


    beforeDestroy: function () {
        if (this.monitorTask) {
            Ext.TaskMgr.stop(this.monitorTask);
        }
        if (this.rendered) {
            Ext.destroy(this.tb);
            var doc = this.getDoc();
            if (doc) {
                try {
                    Ext.EventManager.removeAll(doc);
                    for (var prop in doc) {
                        delete doc[prop];
                    }
                } catch (e) { }
            }
            if (this.wrap) {
                this.wrap.dom.innerHTML = '';
                this.wrap.remove();
            }
        }
        Ext.form.HtmlEditor.superclass.beforeDestroy.call(this);
    },


    onFirstFocus: function () {
        this.activated = true;
        this.disableItems(this.readOnly);
        if (Ext.isGecko) {
            this.win.focus();
            var s = this.win.getSelection();
            if (!s.focusNode || s.focusNode.nodeType != 3) {
                var r = s.getRangeAt(0);
                r.selectNodeContents(this.getEditorBody());
                r.collapse(true);
                this.deferFocus();
            }
            try {
                this.execCmd('useCSS', true);
                this.execCmd('styleWithCSS', false);
            } catch (e) { }
        }
        this.fireEvent('activate', this);
    },


    adjustFont: function (btn) {
        var adjust = btn.getItemId() == 'increasefontsize' ? 1 : -1,
            doc = this.getDoc(),
            v = parseInt(doc.queryCommandValue('FontSize') || 2, 10);
        if ((Ext.isSafari && !Ext.isSafari2) || Ext.isChrome || Ext.isAir) {


            if (v <= 10) {
                v = 1 + adjust;
            } else if (v <= 13) {
                v = 2 + adjust;
            } else if (v <= 16) {
                v = 3 + adjust;
            } else if (v <= 18) {
                v = 4 + adjust;
            } else if (v <= 24) {
                v = 5 + adjust;
            } else {
                v = 6 + adjust;
            }
            v = v.constrain(1, 6);
        } else {
            if (Ext.isSafari) {
                adjust *= 2;
            }
            v = Math.max(1, v + adjust) + (Ext.isSafari ? 'px' : 0);
        }
        this.execCmd('FontSize', v);
    },


    onEditorEvent: function (e) {
        this.updateToolbar();
    },



    updateToolbar: function () {

        if (this.readOnly) {
            return;
        }

        if (!this.activated) {
            this.onFirstFocus();
            return;
        }

        var btns = this.tb.items.map,
            doc = this.getDoc();

        if (this.enableFont && !Ext.isSafari2) {
            var name = (doc.queryCommandValue('FontName') || this.defaultFont).toLowerCase();
            if (name != this.fontSelect.dom.value) {
                this.fontSelect.dom.value = name;
            }
        }
        if (this.enableFormat) {
            btns.bold.toggle(doc.queryCommandState('bold'));
            btns.italic.toggle(doc.queryCommandState('italic'));
            btns.underline.toggle(doc.queryCommandState('underline'));
        }
        if (this.enableAlignments) {
            btns.justifyleft.toggle(doc.queryCommandState('justifyleft'));
            btns.justifycenter.toggle(doc.queryCommandState('justifycenter'));
            btns.justifyright.toggle(doc.queryCommandState('justifyright'));
        }
        if (!Ext.isSafari2 && this.enableLists) {
            btns.insertorderedlist.toggle(doc.queryCommandState('insertorderedlist'));
            btns.insertunorderedlist.toggle(doc.queryCommandState('insertunorderedlist'));
        }

        Ext.menu.MenuMgr.hideAll();

        this.syncValue();
    },


    relayBtnCmd: function (btn) {
        this.relayCmd(btn.getItemId());
    },


    relayCmd: function (cmd, value) {
        (function () {
            this.focus();
            this.execCmd(cmd, value);
            this.updateToolbar();
        }).defer(10, this);
    },


    execCmd: function (cmd, value) {
        var doc = this.getDoc();
        doc.execCommand(cmd, false, value === undefined ? null : value);
        this.syncValue();
    },


    applyCommand: function (e) {
        if (e.ctrlKey) {
            var c = e.getCharCode(), cmd;
            if (c > 0) {
                c = String.fromCharCode(c);
                switch (c) {
                    case 'b':
                        cmd = 'bold';
                        break;
                    case 'i':
                        cmd = 'italic';
                        break;
                    case 'u':
                        cmd = 'underline';
                        break;
                }
                if (cmd) {
                    this.win.focus();
                    this.execCmd(cmd);
                    this.deferFocus();
                    e.preventDefault();
                }
            }
        }
    },


    insertAtCursor: function (text) {
        if (!this.activated) {
            return;
        }
        if (Ext.isIE) {
            this.win.focus();
            var doc = this.getDoc(),
                r = doc.selection.createRange();
            if (r) {
                r.pasteHTML(text);
                this.syncValue();
                this.deferFocus();
            }
        } else {
            this.win.focus();
            this.execCmd('InsertHTML', text);
            this.deferFocus();
        }
    },


    fixKeys: function () {
        if (Ext.isIE) {
            return function (e) {
                var k = e.getKey(),
                    doc = this.getDoc(),
                        r;
                if (k == e.TAB) {
                    e.stopEvent();
                    r = doc.selection.createRange();
                    if (r) {
                        r.collapse(true);
                        r.pasteHTML('&nbsp;&nbsp;&nbsp;&nbsp;');
                        this.deferFocus();
                    }
                } else if (k == e.ENTER) {
                    r = doc.selection.createRange();
                    if (r) {
                        var target = r.parentElement();
                        if (!target || target.tagName.toLowerCase() != 'li') {
                            e.stopEvent();
                            r.pasteHTML('<br />');
                            r.collapse(false);
                            r.select();
                        }
                    }
                }
            };
        } else if (Ext.isOpera) {
            return function (e) {
                var k = e.getKey();
                if (k == e.TAB) {
                    e.stopEvent();
                    this.win.focus();
                    this.execCmd('InsertHTML', '&nbsp;&nbsp;&nbsp;&nbsp;');
                    this.deferFocus();
                }
            };
        } else if (Ext.isWebKit) {
            return function (e) {
                var k = e.getKey();
                if (k == e.TAB) {
                    e.stopEvent();
                    this.execCmd('InsertText', '\t');
                    this.deferFocus();
                } else if (k == e.ENTER) {
                    e.stopEvent();
                    this.execCmd('InsertHtml', '<br /><br />');
                    this.deferFocus();
                }
            };
        }
    } (),


    getToolbar: function () {
        return this.tb;
    },


    buttonTips: {
        bold: {
            title: 'Bold (Ctrl+B)',
            text: 'Make the selected text bold.',
            cls: 'x-html-editor-tip'
        },
        italic: {
            title: 'Italic (Ctrl+I)',
            text: 'Make the selected text italic.',
            cls: 'x-html-editor-tip'
        },
        underline: {
            title: 'Underline (Ctrl+U)',
            text: 'Underline the selected text.',
            cls: 'x-html-editor-tip'
        },
        increasefontsize: {
            title: 'Grow Text',
            text: 'Increase the font size.',
            cls: 'x-html-editor-tip'
        },
        decreasefontsize: {
            title: 'Shrink Text',
            text: 'Decrease the font size.',
            cls: 'x-html-editor-tip'
        },
        backcolor: {
            title: 'Text Highlight Color',
            text: 'Change the background color of the selected text.',
            cls: 'x-html-editor-tip'
        },
        forecolor: {
            title: 'Font Color',
            text: 'Change the color of the selected text.',
            cls: 'x-html-editor-tip'
        },
        justifyleft: {
            title: 'Align Text Left',
            text: 'Align text to the left.',
            cls: 'x-html-editor-tip'
        },
        justifycenter: {
            title: 'Center Text',
            text: 'Center text in the editor.',
            cls: 'x-html-editor-tip'
        },
        justifyright: {
            title: 'Align Text Right',
            text: 'Align text to the right.',
            cls: 'x-html-editor-tip'
        },
        insertunorderedlist: {
            title: 'Bullet List',
            text: 'Start a bulleted list.',
            cls: 'x-html-editor-tip'
        },
        insertorderedlist: {
            title: 'Numbered List',
            text: 'Start a numbered list.',
            cls: 'x-html-editor-tip'
        },
        createlink: {
            title: 'Hyperlink',
            text: 'Make the selected text a hyperlink.',
            cls: 'x-html-editor-tip'
        },
        sourceedit: {
            title: 'Source Edit',
            text: 'Switch to source editing mode.',
            cls: 'x-html-editor-tip'
        }
    }



































});
Ext.reg('htmleditor', Ext.form.HtmlEditor);

Ext.form.TimeField = Ext.extend(Ext.form.ComboBox, {

    minValue: undefined,

    maxValue: undefined,

    minText: "The time in this field must be equal to or after {0}",

    maxText: "The time in this field must be equal to or before {0}",

    invalidText: "{0} is not a valid time",

    format: "g:i A",

    altFormats: "g:ia|g:iA|g:i a|g:i A|h:i|g:i|H:i|ga|ha|gA|h a|g a|g A|gi|hi|gia|hia|g|H|gi a|hi a|giA|hiA|gi A|hi A",

    increment: 15,


    mode: 'local',

    triggerAction: 'all',

    typeAhead: false,




    initDate: '1/1/2008',

    initDateFormat: 'j/n/Y',


    initComponent: function () {
        if (Ext.isDefined(this.minValue)) {
            this.setMinValue(this.minValue, true);
        }
        if (Ext.isDefined(this.maxValue)) {
            this.setMaxValue(this.maxValue, true);
        }
        if (!this.store) {
            this.generateStore(true);
        }
        Ext.form.TimeField.superclass.initComponent.call(this);
    },


    setMinValue: function (value, initial) {
        this.setLimit(value, true, initial);
        return this;
    },


    setMaxValue: function (value, initial) {
        this.setLimit(value, false, initial);
        return this;
    },


    generateStore: function (initial) {
        var min = this.minValue || new Date(this.initDate).clearTime(),
            max = this.maxValue || new Date(this.initDate).clearTime().add('mi', (24 * 60) - 1),
            times = [];

        while (min <= max) {
            times.push(min.dateFormat(this.format));
            min = min.add('mi', this.increment);
        }
        this.bindStore(times, initial);
    },


    setLimit: function (value, isMin, initial) {
        var d;
        if (Ext.isString(value)) {
            d = this.parseDate(value);
        } else if (Ext.isDate(value)) {
            d = value;
        }
        if (d) {
            var val = new Date(this.initDate).clearTime();
            val.setHours(d.getHours(), d.getMinutes(), d.getSeconds(), d.getMilliseconds());
            this[isMin ? 'minValue' : 'maxValue'] = val;
            if (!initial) {
                this.generateStore();
            }
        }
    },


    getValue: function () {
        var v = Ext.form.TimeField.superclass.getValue.call(this);
        return this.formatDate(this.parseDate(v)) || '';
    },


    setValue: function (value) {
        return Ext.form.TimeField.superclass.setValue.call(this, this.formatDate(this.parseDate(value)));
    },


    validateValue: Ext.form.DateField.prototype.validateValue,

    formatDate: Ext.form.DateField.prototype.formatDate,

    parseDate: function (value) {
        if (!value || Ext.isDate(value)) {
            return value;
        }

        var id = this.initDate + ' ',
            idf = this.initDateFormat + ' ',
            v = Date.parseDate(id + value, idf + this.format),
            af = this.altFormats;

        if (!v && af) {
            if (!this.altFormatsArray) {
                this.altFormatsArray = af.split("|");
            }
            for (var i = 0, afa = this.altFormatsArray, len = afa.length; i < len && !v; i++) {
                v = Date.parseDate(id + value, idf + afa[i]);
            }
        }

        return v;
    }
});
Ext.reg('timefield', Ext.form.TimeField);
Ext.form.SliderField = Ext.extend(Ext.form.Field, {


    useTips: true,


    tipText: null,


    actionMode: 'wrap',


    initComponent: function () {
        var cfg = Ext.copyTo({
            id: this.id + '-slider'
        }, this.initialConfig, ['vertical', 'minValue', 'maxValue', 'decimalPrecision', 'keyIncrement', 'increment', 'clickToChange', 'animate']);


        if (this.useTips) {
            var plug = this.tipText ? { getText: this.tipText} : {};
            cfg.plugins = [new Ext.slider.Tip(plug)];
        }
        this.slider = new Ext.Slider(cfg);
        Ext.form.SliderField.superclass.initComponent.call(this);
    },


    onRender: function (ct, position) {
        this.autoCreate = {
            id: this.id,
            name: this.name,
            type: 'hidden',
            tag: 'input'
        };
        Ext.form.SliderField.superclass.onRender.call(this, ct, position);
        this.wrap = this.el.wrap({ cls: 'x-form-field-wrap' });
        this.resizeEl = this.positionEl = this.wrap;
        this.slider.render(this.wrap);
    },


    onResize: function (w, h, aw, ah) {
        Ext.form.SliderField.superclass.onResize.call(this, w, h, aw, ah);
        this.slider.setSize(w, h);
    },


    initEvents: function () {
        Ext.form.SliderField.superclass.initEvents.call(this);
        this.slider.on('change', this.onChange, this);
    },


    onChange: function (slider, v) {
        this.setValue(v, undefined, true);
    },


    onEnable: function () {
        Ext.form.SliderField.superclass.onEnable.call(this);
        this.slider.enable();
    },


    onDisable: function () {
        Ext.form.SliderField.superclass.onDisable.call(this);
        this.slider.disable();
    },


    beforeDestroy: function () {
        Ext.destroy(this.slider);
        Ext.form.SliderField.superclass.beforeDestroy.call(this);
    },


    alignErrorIcon: function () {
        this.errorIcon.alignTo(this.slider.el, 'tl-tr', [2, 0]);
    },


    setMinValue: function (v) {
        this.slider.setMinValue(v);
        return this;
    },


    setMaxValue: function (v) {
        this.slider.setMaxValue(v);
        return this;
    },


    setValue: function (v, animate, silent) {


        if (!silent) {
            this.slider.setValue(v, animate);
        }
        return Ext.form.SliderField.superclass.setValue.call(this, this.slider.getValue());
    },


    getValue: function () {
        return this.slider.getValue();
    }
});

Ext.reg('sliderfield', Ext.form.SliderField);
Ext.form.Label = Ext.extend(Ext.BoxComponent, {





    onRender: function (ct, position) {
        if (!this.el) {
            this.el = document.createElement('label');
            this.el.id = this.getId();
            this.el.innerHTML = this.text ? Ext.util.Format.htmlEncode(this.text) : (this.html || '');
            if (this.forId) {
                this.el.setAttribute('for', this.forId);
            }
        }
        Ext.form.Label.superclass.onRender.call(this, ct, position);
    },


    setText: function (t, encode) {
        var e = encode === false;
        this[!e ? 'text' : 'html'] = t;
        delete this[e ? 'text' : 'html'];
        if (this.rendered) {
            this.el.dom.innerHTML = encode !== false ? Ext.util.Format.htmlEncode(t) : t;
        }
        return this;
    }
});

Ext.reg('label', Ext.form.Label);
Ext.form.Action = function (form, options) {
    this.form = form;
    this.options = options || {};
};


Ext.form.Action.CLIENT_INVALID = 'client';

Ext.form.Action.SERVER_INVALID = 'server';

Ext.form.Action.CONNECT_FAILURE = 'connect';

Ext.form.Action.LOAD_FAILURE = 'load';

Ext.form.Action.prototype = {














    type: 'default',





    run: function (options) {

    },


    success: function (response) {

    },


    handleResponse: function (response) {

    },


    failure: function (response) {
        this.response = response;
        this.failureType = Ext.form.Action.CONNECT_FAILURE;
        this.form.afterAction(this, false);
    },




    processResponse: function (response) {
        this.response = response;
        if (!response.responseText && !response.responseXML) {
            return true;
        }
        this.result = this.handleResponse(response);
        return this.result;
    },


    getUrl: function (appendParams) {
        var url = this.options.url || this.form.url || this.form.el.dom.action;
        if (appendParams) {
            var p = this.getParams();
            if (p) {
                url = Ext.urlAppend(url, p);
            }
        }
        return url;
    },


    getMethod: function () {
        return (this.options.method || this.form.method || this.form.el.dom.method || 'POST').toUpperCase();
    },


    getParams: function () {
        var bp = this.form.baseParams;
        var p = this.options.params;
        if (p) {
            if (typeof p == "object") {
                p = Ext.urlEncode(Ext.applyIf(p, bp));
            } else if (typeof p == 'string' && bp) {
                p += '&' + Ext.urlEncode(bp);
            }
        } else if (bp) {
            p = Ext.urlEncode(bp);
        }
        return p;
    },


    createCallback: function (opts) {
        var opts = opts || {};
        return {
            success: this.success,
            failure: this.failure,
            scope: this,
            timeout: (opts.timeout * 1000) || (this.form.timeout * 1000),
            upload: this.form.fileUpload ? this.success : undefined
        };
    }
};


Ext.form.Action.Submit = function (form, options) {
    Ext.form.Action.Submit.superclass.constructor.call(this, form, options);
};

Ext.extend(Ext.form.Action.Submit, Ext.form.Action, {


    type: 'submit',


    run: function () {
        var o = this.options,
            method = this.getMethod(),
            isGet = method == 'GET';
        if (o.clientValidation === false || this.form.isValid()) {
            if (o.submitEmptyText === false) {
                var fields = this.form.items,
                    emptyFields = [],
                    setupEmptyFields = function (f) {
                        if (f.el.getValue() == f.emptyText) {
                            emptyFields.push(f);
                            f.el.dom.value = "";
                        }
                        if (f.isComposite && f.rendered) {
                            f.items.each(setupEmptyFields);
                        }
                    };

                fields.each(setupEmptyFields);
            }
            Ext.Ajax.request(Ext.apply(this.createCallback(o), {
                form: this.form.el.dom,
                url: this.getUrl(isGet),
                method: method,
                headers: o.headers,
                params: !isGet ? this.getParams() : null,
                isUpload: this.form.fileUpload
            }));
            if (o.submitEmptyText === false) {
                Ext.each(emptyFields, function (f) {
                    if (f.applyEmptyText) {
                        f.applyEmptyText();
                    }
                });
            }
        } else if (o.clientValidation !== false) {
            this.failureType = Ext.form.Action.CLIENT_INVALID;
            this.form.afterAction(this, false);
        }
    },


    success: function (response) {
        var result = this.processResponse(response);
        if (result === true || result.success) {
            this.form.afterAction(this, true);
            return;
        }
        if (result.errors) {
            this.form.markInvalid(result.errors);
        }
        this.failureType = Ext.form.Action.SERVER_INVALID;
        this.form.afterAction(this, false);
    },


    handleResponse: function (response) {
        if (this.form.errorReader) {
            var rs = this.form.errorReader.read(response);
            var errors = [];
            if (rs.records) {
                for (var i = 0, len = rs.records.length; i < len; i++) {
                    var r = rs.records[i];
                    errors[i] = r.data;
                }
            }
            if (errors.length < 1) {
                errors = null;
            }
            return {
                success: rs.success,
                errors: errors
            };
        }
        return Ext.decode(response.responseText);
    }
});



Ext.form.Action.Load = function (form, options) {
    Ext.form.Action.Load.superclass.constructor.call(this, form, options);
    this.reader = this.form.reader;
};

Ext.extend(Ext.form.Action.Load, Ext.form.Action, {

    type: 'load',


    run: function () {
        Ext.Ajax.request(Ext.apply(
                this.createCallback(this.options), {
                    method: this.getMethod(),
                    url: this.getUrl(false),
                    headers: this.options.headers,
                    params: this.getParams()
                }));
    },


    success: function (response) {
        var result = this.processResponse(response);
        if (result === true || !result.success || !result.data) {
            this.failureType = Ext.form.Action.LOAD_FAILURE;
            this.form.afterAction(this, false);
            return;
        }
        this.form.clearInvalid();
        this.form.setValues(result.data);
        this.form.afterAction(this, true);
    },


    handleResponse: function (response) {
        if (this.form.reader) {
            var rs = this.form.reader.read(response);
            var data = rs.records && rs.records[0] ? rs.records[0].data : null;
            return {
                success: rs.success,
                data: data
            };
        }
        return Ext.decode(response.responseText);
    }
});




Ext.form.Action.DirectLoad = Ext.extend(Ext.form.Action.Load, {
    constructor: function (form, opts) {
        Ext.form.Action.DirectLoad.superclass.constructor.call(this, form, opts);
    },
    type: 'directload',

    run: function () {
        var args = this.getParams();
        args.push(this.success, this);
        this.form.api.load.apply(window, args);
    },

    getParams: function () {
        var buf = [], o = {};
        var bp = this.form.baseParams;
        var p = this.options.params;
        Ext.apply(o, p, bp);
        var paramOrder = this.form.paramOrder;
        if (paramOrder) {
            for (var i = 0, len = paramOrder.length; i < len; i++) {
                buf.push(o[paramOrder[i]]);
            }
        } else if (this.form.paramsAsHash) {
            buf.push(o);
        }
        return buf;
    },



    processResponse: function (result) {
        this.result = result;
        return result;
    },

    success: function (response, trans) {
        if (trans.type == Ext.Direct.exceptions.SERVER) {
            response = {};
        }
        Ext.form.Action.DirectLoad.superclass.success.call(this, response);
    }
});


Ext.form.Action.DirectSubmit = Ext.extend(Ext.form.Action.Submit, {
    constructor: function (form, opts) {
        Ext.form.Action.DirectSubmit.superclass.constructor.call(this, form, opts);
    },
    type: 'directsubmit',

    run: function () {
        var o = this.options;
        if (o.clientValidation === false || this.form.isValid()) {


            this.success.params = this.getParams();
            this.form.api.submit(this.form.el.dom, this.success, this);
        } else if (o.clientValidation !== false) {
            this.failureType = Ext.form.Action.CLIENT_INVALID;
            this.form.afterAction(this, false);
        }
    },

    getParams: function () {
        var o = {};
        var bp = this.form.baseParams;
        var p = this.options.params;
        Ext.apply(o, p, bp);
        return o;
    },



    processResponse: function (result) {
        this.result = result;
        return result;
    },

    success: function (response, trans) {
        if (trans.type == Ext.Direct.exceptions.SERVER) {
            response = {};
        }
        Ext.form.Action.DirectSubmit.superclass.success.call(this, response);
    }
});

Ext.form.Action.ACTION_TYPES = {
    'load': Ext.form.Action.Load,
    'submit': Ext.form.Action.Submit,
    'directload': Ext.form.Action.DirectLoad,
    'directsubmit': Ext.form.Action.DirectSubmit
};

Ext.form.VTypes = function () {

    var alpha = /^[a-zA-Z_]+$/,
        alphanum = /^[a-zA-Z0-9_]+$/,
        email = /^(\w+)([\-+.][\w]+)*@(\w[\-\w]*\.){1,5}([A-Za-z]){2,6}$/,
        url = /(((^https?)|(^ftp)):\/\/([\-\w]+\.)+\w{2,3}(\/[%\-\w]+(\.\w{2,})?)*(([\w\-\.\?\\\/+@&#;`~=%!]*)(\.\w{2,})?)*\/?)/i;


    return {

        'email': function (v) {
            return email.test(v);
        },

        'emailText': 'This field should be an e-mail address in the format "user@example.com"',

        'emailMask': /[a-z0-9_\.\-@\+]/i,


        'url': function (v) {
            return url.test(v);
        },

        'urlText': 'This field should be a URL in the format "http:/' + '/www.example.com"',


        'alpha': function (v) {
            return alpha.test(v);
        },

        'alphaText': 'This field should only contain letters and _',

        'alphaMask': /[a-z_]/i,


        'alphanum': function (v) {
            return alphanum.test(v);
        },

        'alphanumText': 'This field should only contain letters, numbers and _',

        'alphanumMask': /[a-z0-9_]/i
    };
} ();

Ext.grid.GridPanel = Ext.extend(Ext.Panel, {

    autoExpandColumn: false,


    autoExpandMax: 1000,


    autoExpandMin: 50,


    columnLines: false,






    ddText: '{0} selected row{1}',


    deferRowRender: true,




    enableColumnHide: true,


    enableColumnMove: true,


    enableDragDrop: false,


    enableHdMenu: true,



    loadMask: false,



    minColumnWidth: 25,





    stripeRows: false,


    trackMouseOver: true,


    stateEvents: ['columnmove', 'columnresize', 'sortchange', 'groupchange'],


    view: null,


    bubbleEvents: [],




    rendered: false,


    viewReady: false,


    initComponent: function () {
        Ext.grid.GridPanel.superclass.initComponent.call(this);

        if (this.columnLines) {
            this.cls = (this.cls || '') + ' x-grid-with-col-lines';
        }


        this.autoScroll = false;
        this.autoWidth = false;

        if (Ext.isArray(this.columns)) {
            this.colModel = new Ext.grid.ColumnModel(this.columns);
            delete this.columns;
        }


        if (this.ds) {
            this.store = this.ds;
            delete this.ds;
        }
        if (this.cm) {
            this.colModel = this.cm;
            delete this.cm;
        }
        if (this.sm) {
            this.selModel = this.sm;
            delete this.sm;
        }
        this.store = Ext.StoreMgr.lookup(this.store);

        this.addEvents(


            'click',

            'dblclick',

            'contextmenu',

            'mousedown',

            'mouseup',

            'mouseover',

            'mouseout',

            'keypress',

            'keydown',



            'cellmousedown',

            'rowmousedown',

            'headermousedown',


            'groupmousedown',


            'rowbodymousedown',


            'containermousedown',


            'cellclick',

            'celldblclick',

            'rowclick',

            'rowdblclick',

            'headerclick',

            'headerdblclick',

            'groupclick',

            'groupdblclick',

            'containerclick',

            'containerdblclick',


            'rowbodyclick',

            'rowbodydblclick',


            'rowcontextmenu',

            'cellcontextmenu',

            'headercontextmenu',

            'groupcontextmenu',

            'containercontextmenu',

            'rowbodycontextmenu',

            'bodyscroll',

            'columnresize',

            'columnmove',

            'sortchange',

            'groupchange',

            'reconfigure',

            'viewready'
        );
    },


    onRender: function (ct, position) {
        Ext.grid.GridPanel.superclass.onRender.apply(this, arguments);

        var c = this.getGridEl();

        this.el.addClass('x-grid-panel');

        this.mon(c, {
            scope: this,
            mousedown: this.onMouseDown,
            click: this.onClick,
            dblclick: this.onDblClick,
            contextmenu: this.onContextMenu
        });

        this.relayEvents(c, ['mousedown', 'mouseup', 'mouseover', 'mouseout', 'keypress', 'keydown']);

        var view = this.getView();
        view.init(this);
        view.render();
        this.getSelectionModel().init(this);
    },


    initEvents: function () {
        Ext.grid.GridPanel.superclass.initEvents.call(this);

        if (this.loadMask) {
            this.loadMask = new Ext.LoadMask(this.bwrap,
                    Ext.apply({ store: this.store }, this.loadMask));
        }
    },

    initStateEvents: function () {
        Ext.grid.GridPanel.superclass.initStateEvents.call(this);
        this.mon(this.colModel, 'hiddenchange', this.saveState, this, { delay: 100 });
    },

    applyState: function (state) {
        var cm = this.colModel,
            cs = state.columns,
            store = this.store,
            s,
            c,
            oldIndex;

        if (cs) {
            for (var i = 0, len = cs.length; i < len; i++) {
                s = cs[i];
                c = cm.getColumnById(s.id);
                if (c) {
                    cm.setState(s.id, {
                        hidden: s.hidden,
                        width: s.width
                    });
                    oldIndex = cm.getIndexById(s.id);
                    if (oldIndex != i) {
                        cm.moveColumn(oldIndex, i);
                    }
                }
            }
        }
        if (store) {
            s = state.sort;
            if (s) {
                store[store.remoteSort ? 'setDefaultSort' : 'sort'](s.field, s.direction);
            }
            s = state.group;
            if (store.groupBy) {
                if (s) {
                    store.groupBy(s);
                } else {
                    store.clearGrouping();
                }
            }

        }
        var o = Ext.apply({}, state);
        delete o.columns;
        delete o.sort;
        Ext.grid.GridPanel.superclass.applyState.call(this, o);
    },

    getState: function () {
        var o = { columns: [] },
            store = this.store,
            ss,
            gs;

        for (var i = 0, c; (c = this.colModel.config[i]); i++) {
            o.columns[i] = {
                id: c.id,
                width: c.width
            };
            if (c.hidden) {
                o.columns[i].hidden = true;
            }
        }
        if (store) {
            ss = store.getSortState();
            if (ss) {
                o.sort = ss;
            }
            if (store.getGroupState) {
                gs = store.getGroupState();
                if (gs) {
                    o.group = gs;
                }
            }
        }
        return o;
    },


    afterRender: function () {
        Ext.grid.GridPanel.superclass.afterRender.call(this);
        var v = this.view;
        this.on('bodyresize', v.layout, v);
        v.layout(true);
        if (this.deferRowRender) {
            if (!this.deferRowRenderTask) {
                this.deferRowRenderTask = new Ext.util.DelayedTask(v.afterRender, this.view);
            }
            this.deferRowRenderTask.delay(10);
        } else {
            v.afterRender();
        }
        this.viewReady = true;
    },


    reconfigure: function (store, colModel) {
        var rendered = this.rendered;
        if (rendered) {
            if (this.loadMask) {
                this.loadMask.destroy();
                this.loadMask = new Ext.LoadMask(this.bwrap,
                        Ext.apply({}, { store: store }, this.initialConfig.loadMask));
            }
        }
        if (this.view) {
            this.view.initData(store, colModel);
        }
        this.store = store;
        this.colModel = colModel;
        if (rendered) {
            this.view.refresh(true);
        }
        this.fireEvent('reconfigure', this, store, colModel);
    },


    onDestroy: function () {
        if (this.deferRowRenderTask && this.deferRowRenderTask.cancel) {
            this.deferRowRenderTask.cancel();
        }
        if (this.rendered) {
            Ext.destroy(this.view, this.loadMask);
        } else if (this.store && this.store.autoDestroy) {
            this.store.destroy();
        }
        Ext.destroy(this.colModel, this.selModel);
        this.store = this.selModel = this.colModel = this.view = this.loadMask = null;
        Ext.grid.GridPanel.superclass.onDestroy.call(this);
    },


    processEvent: function (name, e) {
        this.view.processEvent(name, e);
    },


    onClick: function (e) {
        this.processEvent('click', e);
    },


    onMouseDown: function (e) {
        this.processEvent('mousedown', e);
    },


    onContextMenu: function (e, t) {
        this.processEvent('contextmenu', e);
    },


    onDblClick: function (e) {
        this.processEvent('dblclick', e);
    },


    walkCells: function (row, col, step, fn, scope) {
        var cm = this.colModel,
            clen = cm.getColumnCount(),
            ds = this.store,
            rlen = ds.getCount(),
            first = true;

        if (step < 0) {
            if (col < 0) {
                row--;
                first = false;
            }
            while (row >= 0) {
                if (!first) {
                    col = clen - 1;
                }
                first = false;
                while (col >= 0) {
                    if (fn.call(scope || this, row, col, cm) === true) {
                        return [row, col];
                    }
                    col--;
                }
                row--;
            }
        } else {
            if (col >= clen) {
                row++;
                first = false;
            }
            while (row < rlen) {
                if (!first) {
                    col = 0;
                }
                first = false;
                while (col < clen) {
                    if (fn.call(scope || this, row, col, cm) === true) {
                        return [row, col];
                    }
                    col++;
                }
                row++;
            }
        }
        return null;
    },


    getGridEl: function () {
        return this.body;
    },


    stopEditing: Ext.emptyFn,


    getSelectionModel: function () {
        if (!this.selModel) {
            this.selModel = new Ext.grid.RowSelectionModel(
                    this.disableSelection ? { selectRow: Ext.emptyFn} : null);
        }
        return this.selModel;
    },


    getStore: function () {
        return this.store;
    },


    getColumnModel: function () {
        return this.colModel;
    },


    getView: function () {
        if (!this.view) {
            this.view = new Ext.grid.GridView(this.viewConfig);
        }

        return this.view;
    },

    getDragDropText: function () {
        var count = this.selModel.getCount();
        return String.format(this.ddText, count, count == 1 ? '' : 's');
    }



















































});
Ext.reg('grid', Ext.grid.GridPanel);
Ext.grid.PivotGrid = Ext.extend(Ext.grid.GridPanel, {


    aggregator: 'sum',


    renderer: undefined,








    initComponent: function () {
        Ext.grid.PivotGrid.superclass.initComponent.apply(this, arguments);

        this.initAxes();


        this.enableColumnResize = false;

        this.viewConfig = Ext.apply(this.viewConfig || {}, {
            forceFit: true
        });



        this.colModel = new Ext.grid.ColumnModel({});
    },


    getAggregator: function () {
        if (typeof this.aggregator == 'string') {
            return Ext.grid.PivotAggregatorMgr.types[this.aggregator];
        } else {
            return this.aggregator;
        }
    },


    setAggregator: function (aggregator) {
        this.aggregator = aggregator;
    },


    setMeasure: function (measure) {
        this.measure = measure;
    },


    setLeftAxis: function (axis, refresh) {

        this.leftAxis = axis;

        if (refresh) {
            this.view.refresh();
        }
    },


    setTopAxis: function (axis, refresh) {

        this.topAxis = axis;

        if (refresh) {
            this.view.refresh();
        }
    },


    initAxes: function () {
        var PivotAxis = Ext.grid.PivotAxis;

        if (!(this.leftAxis instanceof PivotAxis)) {
            this.setLeftAxis(new PivotAxis({
                orientation: 'vertical',
                dimensions: this.leftAxis || [],
                store: this.store
            }));
        };

        if (!(this.topAxis instanceof PivotAxis)) {
            this.setTopAxis(new PivotAxis({
                orientation: 'horizontal',
                dimensions: this.topAxis || [],
                store: this.store
            }));
        };
    },


    extractData: function () {
        var records = this.store.data.items,
            recCount = records.length,
            cells = [],
            record, i, j, k;

        if (recCount == 0) {
            return [];
        }

        var leftTuples = this.leftAxis.getTuples(),
            leftCount = leftTuples.length,
            topTuples = this.topAxis.getTuples(),
            topCount = topTuples.length,
            aggregator = this.getAggregator();

        for (i = 0; i < recCount; i++) {
            record = records[i];

            for (j = 0; j < leftCount; j++) {
                cells[j] = cells[j] || [];

                if (leftTuples[j].matcher(record) === true) {
                    for (k = 0; k < topCount; k++) {
                        cells[j][k] = cells[j][k] || [];

                        if (topTuples[k].matcher(record)) {
                            cells[j][k].push(record);
                        }
                    }
                }
            }
        }

        var rowCount = cells.length,
            colCount, row;

        for (i = 0; i < rowCount; i++) {
            row = cells[i];
            colCount = row.length;

            for (j = 0; j < colCount; j++) {
                cells[i][j] = aggregator(cells[i][j], this.measure);
            }
        }

        return cells;
    },


    getView: function () {
        if (!this.view) {
            this.view = new Ext.grid.PivotGridView(this.viewConfig);
        }

        return this.view;
    }
});

Ext.reg('pivotgrid', Ext.grid.PivotGrid);


Ext.grid.PivotAggregatorMgr = new Ext.AbstractManager();

Ext.grid.PivotAggregatorMgr.registerType('sum', function (records, measure) {
    var length = records.length,
        total = 0,
        i;

    for (i = 0; i < length; i++) {
        total += records[i].get(measure);
    }

    return total;
});

Ext.grid.PivotAggregatorMgr.registerType('avg', function (records, measure) {
    var length = records.length,
        total = 0,
        i;

    for (i = 0; i < length; i++) {
        total += records[i].get(measure);
    }

    return (total / length) || 'n/a';
});

Ext.grid.PivotAggregatorMgr.registerType('min', function (records, measure) {
    var data = [],
        length = records.length,
        i;

    for (i = 0; i < length; i++) {
        data.push(records[i].get(measure));
    }

    return Math.min.apply(this, data) || 'n/a';
});

Ext.grid.PivotAggregatorMgr.registerType('max', function (records, measure) {
    var data = [],
        length = records.length,
        i;

    for (i = 0; i < length; i++) {
        data.push(records[i].get(measure));
    }

    return Math.max.apply(this, data) || 'n/a';
});

Ext.grid.PivotAggregatorMgr.registerType('count', function (records, measure) {
    return records.length;
});
Ext.grid.GridView = Ext.extend(Ext.util.Observable, {











    deferEmptyText: true,


    scrollOffset: undefined,


    autoFill: false,


    forceFit: false,


    sortClasses: ['sort-asc', 'sort-desc'],


    sortAscText: 'Sort Ascending',


    sortDescText: 'Sort Descending',


    columnsText: 'Columns',


    selectedRowClass: 'x-grid3-row-selected',


    borderWidth: 2,
    tdClass: 'x-grid3-cell',
    hdCls: 'x-grid3-hd',



    markDirty: true,


    cellSelectorDepth: 4,


    rowSelectorDepth: 10,


    rowBodySelectorDepth: 10,


    cellSelector: 'td.x-grid3-cell',


    rowSelector: 'div.x-grid3-row',


    rowBodySelector: 'div.x-grid3-row-body',


    firstRowCls: 'x-grid3-row-first',
    lastRowCls: 'x-grid3-row-last',
    rowClsRe: /(?:^|\s+)x-grid3-row-(first|last|alt)(?:\s+|$)/g,


    headerMenuOpenCls: 'x-grid3-hd-menu-open',


    rowOverCls: 'x-grid3-row-over',

    constructor: function (config) {
        Ext.apply(this, config);


        this.addEvents(

            'beforerowremoved',


            'beforerowsinserted',


            'beforerefresh',


            'rowremoved',


            'rowsinserted',


            'rowupdated',


            'refresh'
        );

        Ext.grid.GridView.superclass.constructor.call(this);
    },




    masterTpl: new Ext.Template(
        '<div class="x-grid3" hidefocus="true">',
            '<div class="x-grid3-viewport">',
                '<div class="x-grid3-header">',
                    '<div class="x-grid3-header-inner">',
                        '<div class="x-grid3-header-offset" style="{ostyle}">{header}</div>',
                    '</div>',
                    '<div class="x-clear"></div>',
                '</div>',
                '<div class="x-grid3-scroller">',
                    '<div class="x-grid3-body" style="{bstyle}">{body}</div>',
                    '<a href="#" class="x-grid3-focus" tabIndex="-1"></a>',
                '</div>',
            '</div>',
            '<div class="x-grid3-resize-marker">&#160;</div>',
            '<div class="x-grid3-resize-proxy">&#160;</div>',
        '</div>'
    ),


    headerTpl: new Ext.Template(
        '<table border="0" cellspacing="0" cellpadding="0" style="{tstyle}">',
            '<thead>',
                '<tr class="x-grid3-hd-row">{cells}</tr>',
            '</thead>',
        '</table>'
    ),


    bodyTpl: new Ext.Template('{rows}'),


    cellTpl: new Ext.Template(
        '<td class="x-grid3-col x-grid3-cell x-grid3-td-{id} {css}" style="{style}" tabIndex="0" {cellAttr}>',
            '<div class="x-grid3-cell-inner x-grid3-col-{id}" unselectable="on" {attr}>{value}</div>',
        '</td>'
    ),


    initTemplates: function () {
        var templates = this.templates || {},
            template, name,

            headerCellTpl = new Ext.Template(
                '<td class="x-grid3-hd x-grid3-cell x-grid3-td-{id} {css}" style="{style}">',
                    '<div {tooltip} {attr} class="x-grid3-hd-inner x-grid3-hd-{id}" unselectable="on" style="{istyle}">',
                        this.grid.enableHdMenu ? '<a class="x-grid3-hd-btn" href="#"></a>' : '',
                        '{value}',
                        '<img alt="" class="x-grid3-sort-icon" src="', Ext.BLANK_IMAGE_URL, '" />',
                    '</div>',
                '</td>'
            ),

            rowBodyText = [
                '<tr class="x-grid3-row-body-tr" style="{bodyStyle}">',
                    '<td colspan="{cols}" class="x-grid3-body-cell" tabIndex="0" hidefocus="on">',
                        '<div class="x-grid3-row-body">{body}</div>',
                    '</td>',
                '</tr>'
            ].join(""),

            innerText = [
                '<table class="x-grid3-row-table" border="0" cellspacing="0" cellpadding="0" style="{tstyle}">',
                     '<tbody>',
                        '<tr>{cells}</tr>',
                        this.enableRowBody ? rowBodyText : '',
                     '</tbody>',
                '</table>'
            ].join("");

        Ext.applyIf(templates, {
            hcell: headerCellTpl,
            cell: this.cellTpl,
            body: this.bodyTpl,
            header: this.headerTpl,
            master: this.masterTpl,
            row: new Ext.Template('<div class="x-grid3-row {alt}" style="{tstyle}">' + innerText + '</div>'),
            rowInner: new Ext.Template(innerText)
        });

        for (name in templates) {
            template = templates[name];

            if (template && Ext.isFunction(template.compile) && !template.compiled) {
                template.disableFormats = true;
                template.compile();
            }
        }

        this.templates = templates;
        this.colRe = new RegExp('x-grid3-td-([^\\s]+)', '');
    },


    fly: function (el) {
        if (!this._flyweight) {
            this._flyweight = new Ext.Element.Flyweight(document.body);
        }
        this._flyweight.dom = el;
        return this._flyweight;
    },


    getEditorParent: function () {
        return this.scroller.dom;
    },


    initElements: function () {
        var Element = Ext.Element,
            el = Ext.get(this.grid.getGridEl().dom.firstChild),
            mainWrap = new Element(el.child('div.x-grid3-viewport')),
            mainHd = new Element(mainWrap.child('div.x-grid3-header')),
            scroller = new Element(mainWrap.child('div.x-grid3-scroller'));

        if (this.grid.hideHeaders) {
            mainHd.setDisplayed(false);
        }

        if (this.forceFit) {
            scroller.setStyle('overflow-x', 'hidden');
        }



        Ext.apply(this, {
            el: el,
            mainWrap: mainWrap,
            scroller: scroller,
            mainHd: mainHd,
            innerHd: mainHd.child('div.x-grid3-header-inner').dom,
            mainBody: new Element(Element.fly(scroller).child('div.x-grid3-body')),
            focusEl: new Element(Element.fly(scroller).child('a')),

            resizeMarker: new Element(el.child('div.x-grid3-resize-marker')),
            resizeProxy: new Element(el.child('div.x-grid3-resize-proxy'))
        });

        this.focusEl.swallowEvent('click', true);
    },


    getRows: function () {
        return this.hasRows() ? this.mainBody.dom.childNodes : [];
    },




    findCell: function (el) {
        if (!el) {
            return false;
        }
        return this.fly(el).findParent(this.cellSelector, this.cellSelectorDepth);
    },


    findCellIndex: function (el, requiredCls) {
        var cell = this.findCell(el),
            hasCls;

        if (cell) {
            hasCls = this.fly(cell).hasClass(requiredCls);
            if (!requiredCls || hasCls) {
                return this.getCellIndex(cell);
            }
        }
        return false;
    },


    getCellIndex: function (el) {
        if (el) {
            var match = el.className.match(this.colRe);

            if (match && match[1]) {
                return this.cm.getIndexById(match[1]);
            }
        }
        return false;
    },


    findHeaderCell: function (el) {
        var cell = this.findCell(el);
        return cell && this.fly(cell).hasClass(this.hdCls) ? cell : null;
    },


    findHeaderIndex: function (el) {
        return this.findCellIndex(el, this.hdCls);
    },


    findRow: function (el) {
        if (!el) {
            return false;
        }
        return this.fly(el).findParent(this.rowSelector, this.rowSelectorDepth);
    },


    findRowIndex: function (el) {
        var row = this.findRow(el);
        return row ? row.rowIndex : false;
    },


    findRowBody: function (el) {
        if (!el) {
            return false;
        }

        return this.fly(el).findParent(this.rowBodySelector, this.rowBodySelectorDepth);
    },




    getRow: function (row) {
        return this.getRows()[row];
    },


    getCell: function (row, col) {
        return Ext.fly(this.getRow(row)).query(this.cellSelector)[col];
    },


    getHeaderCell: function (index) {
        return this.mainHd.dom.getElementsByTagName('td')[index];
    },




    addRowClass: function (rowId, cls) {
        var row = this.getRow(rowId);
        if (row) {
            this.fly(row).addClass(cls);
        }
    },


    removeRowClass: function (row, cls) {
        var r = this.getRow(row);
        if (r) {
            this.fly(r).removeClass(cls);
        }
    },


    removeRow: function (row) {
        Ext.removeNode(this.getRow(row));
        this.syncFocusEl(row);
    },


    removeRows: function (firstRow, lastRow) {
        var bd = this.mainBody.dom,
            rowIndex;

        for (rowIndex = firstRow; rowIndex <= lastRow; rowIndex++) {
            Ext.removeNode(bd.childNodes[firstRow]);
        }

        this.syncFocusEl(firstRow);
    },




    getScrollState: function () {
        var sb = this.scroller.dom;

        return {
            left: sb.scrollLeft,
            top: sb.scrollTop
        };
    },


    restoreScroll: function (state) {
        var sb = this.scroller.dom;
        sb.scrollLeft = state.left;
        sb.scrollTop = state.top;
    },


    scrollToTop: function () {
        var dom = this.scroller.dom;

        dom.scrollTop = 0;
        dom.scrollLeft = 0;
    },


    syncScroll: function () {
        this.syncHeaderScroll();
        var mb = this.scroller.dom;
        this.grid.fireEvent('bodyscroll', mb.scrollLeft, mb.scrollTop);
    },


    syncHeaderScroll: function () {
        var innerHd = this.innerHd,
            scrollLeft = this.scroller.dom.scrollLeft;

        innerHd.scrollLeft = scrollLeft;
        innerHd.scrollLeft = scrollLeft;
    },


    updateSortIcon: function (col, dir) {
        var sortClasses = this.sortClasses,
            sortClass = sortClasses[dir == "DESC" ? 1 : 0],
            headers = this.mainHd.select('td').removeClass(sortClasses);

        headers.item(col).addClass(sortClass);
    },


    updateAllColumnWidths: function () {
        var totalWidth = this.getTotalWidth(),
            colCount = this.cm.getColumnCount(),
            rows = this.getRows(),
            rowCount = rows.length,
            widths = [],
            row, rowFirstChild, trow, i, j;

        for (i = 0; i < colCount; i++) {
            widths[i] = this.getColumnWidth(i);
            this.getHeaderCell(i).style.width = widths[i];
        }

        this.updateHeaderWidth();

        for (i = 0; i < rowCount; i++) {
            row = rows[i];
            row.style.width = totalWidth;
            rowFirstChild = row.firstChild;

            if (rowFirstChild) {
                rowFirstChild.style.width = totalWidth;
                trow = rowFirstChild.rows[0];

                for (j = 0; j < colCount; j++) {
                    trow.childNodes[j].style.width = widths[j];
                }
            }
        }

        this.onAllColumnWidthsUpdated(widths, totalWidth);
    },


    updateColumnWidth: function (column, width) {
        var columnWidth = this.getColumnWidth(column),
            totalWidth = this.getTotalWidth(),
            headerCell = this.getHeaderCell(column),
            nodes = this.getRows(),
            nodeCount = nodes.length,
            row, i, firstChild;

        this.updateHeaderWidth();
        headerCell.style.width = columnWidth;

        for (i = 0; i < nodeCount; i++) {
            row = nodes[i];
            firstChild = row.firstChild;

            row.style.width = totalWidth;
            if (firstChild) {
                firstChild.style.width = totalWidth;
                firstChild.rows[0].childNodes[column].style.width = columnWidth;
            }
        }

        this.onColumnWidthUpdated(column, columnWidth, totalWidth);
    },


    updateColumnHidden: function (col, hidden) {
        var totalWidth = this.getTotalWidth(),
            display = hidden ? 'none' : '',
            headerCell = this.getHeaderCell(col),
            nodes = this.getRows(),
            nodeCount = nodes.length,
            row, rowFirstChild, i;

        this.updateHeaderWidth();
        headerCell.style.display = display;

        for (i = 0; i < nodeCount; i++) {
            row = nodes[i];
            row.style.width = totalWidth;
            rowFirstChild = row.firstChild;

            if (rowFirstChild) {
                rowFirstChild.style.width = totalWidth;
                rowFirstChild.rows[0].childNodes[col].style.display = display;
            }
        }

        this.onColumnHiddenUpdated(col, hidden, totalWidth);
        delete this.lastViewWidth;
        this.layout();
    },


    doRender: function (columns, records, store, startRow, colCount, stripe) {
        var templates = this.templates,
            cellTemplate = templates.cell,
            rowTemplate = templates.row,
            last = colCount - 1,
            tstyle = 'width:' + this.getTotalWidth() + ';',

            rowBuffer = [],
            colBuffer = [],
            rowParams = { tstyle: tstyle },
            meta = {},
            len = records.length,
            alt,
            column,
            record, i, j, rowIndex;


        for (j = 0; j < len; j++) {
            record = records[j];
            colBuffer = [];

            rowIndex = j + startRow;


            for (i = 0; i < colCount; i++) {
                column = columns[i];

                meta.id = column.id;
                meta.css = i === 0 ? 'x-grid3-cell-first ' : (i == last ? 'x-grid3-cell-last ' : '');
                meta.attr = meta.cellAttr = '';
                meta.style = column.style;
                meta.value = column.renderer.call(column.scope, record.data[column.name], meta, record, rowIndex, i, store);

                if (Ext.isEmpty(meta.value)) {
                    meta.value = '&#160;';
                }

                if (this.markDirty && record.dirty && typeof record.modified[column.name] != 'undefined') {
                    meta.css += ' x-grid3-dirty-cell';
                }

                colBuffer[colBuffer.length] = cellTemplate.apply(meta);
            }

            alt = [];

            if (stripe && ((rowIndex + 1) % 2 === 0)) {
                alt[0] = 'x-grid3-row-alt';
            }

            if (record.dirty) {
                alt[1] = ' x-grid3-dirty-row';
            }

            rowParams.cols = colCount;

            if (this.getRowClass) {
                alt[2] = this.getRowClass(record, rowIndex, rowParams, store);
            }

            rowParams.alt = alt.join(' ');
            rowParams.cells = colBuffer.join('');

            rowBuffer[rowBuffer.length] = rowTemplate.apply(rowParams);
        }

        return rowBuffer.join('');
    },


    processRows: function (startRow, skipStripe) {
        if (!this.ds || this.ds.getCount() < 1) {
            return;
        }

        var rows = this.getRows(),
            length = rows.length,
            row, i;

        skipStripe = skipStripe || !this.grid.stripeRows;
        startRow = startRow || 0;

        for (i = 0; i < length; i++) {
            row = rows[i];
            if (row) {
                row.rowIndex = i;
                if (!skipStripe) {
                    row.className = row.className.replace(this.rowClsRe, ' ');
                    if ((i + 1) % 2 === 0) {
                        row.className += ' x-grid3-row-alt';
                    }
                }
            }
        }


        if (startRow === 0) {
            Ext.fly(rows[0]).addClass(this.firstRowCls);
        }

        Ext.fly(rows[length - 1]).addClass(this.lastRowCls);
    },


    afterRender: function () {
        if (!this.ds || !this.cm) {
            return;
        }

        this.mainBody.dom.innerHTML = this.renderBody() || '&#160;';
        this.processRows(0, true);

        if (this.deferEmptyText !== true) {
            this.applyEmptyText();
        }

        this.grid.fireEvent('viewready', this.grid);
    },


    afterRenderUI: function () {
        var grid = this.grid;

        this.initElements();


        Ext.fly(this.innerHd).on('click', this.handleHdDown, this);

        this.mainHd.on({
            scope: this,
            mouseover: this.handleHdOver,
            mouseout: this.handleHdOut,
            mousemove: this.handleHdMove
        });

        this.scroller.on('scroll', this.syncScroll, this);

        if (grid.enableColumnResize !== false) {
            this.splitZone = new Ext.grid.GridView.SplitDragZone(grid, this.mainHd.dom);
        }

        if (grid.enableColumnMove) {
            this.columnDrag = new Ext.grid.GridView.ColumnDragZone(grid, this.innerHd);
            this.columnDrop = new Ext.grid.HeaderDropZone(grid, this.mainHd.dom);
        }

        if (grid.enableHdMenu !== false) {
            this.hmenu = new Ext.menu.Menu({ id: grid.id + '-hctx' });
            this.hmenu.add(
                { itemId: 'asc', text: this.sortAscText, cls: 'xg-hmenu-sort-asc' },
                { itemId: 'desc', text: this.sortDescText, cls: 'xg-hmenu-sort-desc' }
            );

            if (grid.enableColumnHide !== false) {
                this.colMenu = new Ext.menu.Menu({ id: grid.id + '-hcols-menu' });
                this.colMenu.on({
                    scope: this,
                    beforeshow: this.beforeColMenuShow,
                    itemclick: this.handleHdMenuClick
                });
                this.hmenu.add('-', {
                    itemId: 'columns',
                    hideOnClick: false,
                    text: this.columnsText,
                    menu: this.colMenu,
                    iconCls: 'x-cols-icon'
                });
            }

            this.hmenu.on('itemclick', this.handleHdMenuClick, this);
        }

        if (grid.trackMouseOver) {
            this.mainBody.on({
                scope: this,
                mouseover: this.onRowOver,
                mouseout: this.onRowOut
            });
        }

        if (grid.enableDragDrop || grid.enableDrag) {
            this.dragZone = new Ext.grid.GridDragZone(grid, {
                ddGroup: grid.ddGroup || 'GridDD'
            });
        }

        this.updateHeaderSortState();
    },


    renderUI: function () {
        var templates = this.templates;

        return templates.master.apply({
            body: templates.body.apply({ rows: '&#160;' }),
            header: this.renderHeaders(),
            ostyle: 'width:' + this.getOffsetWidth() + ';',
            bstyle: 'width:' + this.getTotalWidth() + ';'
        });
    },


    processEvent: function (name, e) {
        var target = e.getTarget(),
            grid = this.grid,
            header = this.findHeaderIndex(target),
            row, cell, col, body;

        grid.fireEvent(name, e);

        if (header !== false) {
            grid.fireEvent('header' + name, grid, header, e);
        } else {
            row = this.findRowIndex(target);




            if (row !== false) {
                cell = this.findCellIndex(target);
                if (cell !== false) {
                    col = grid.colModel.getColumnAt(cell);
                    if (grid.fireEvent('cell' + name, grid, row, cell, e) !== false) {
                        if (!col || (col.processEvent && (col.processEvent(name, e, grid, row, cell) !== false))) {
                            grid.fireEvent('row' + name, grid, row, e);
                        }
                    }
                } else {
                    if (grid.fireEvent('row' + name, grid, row, e) !== false) {
                        (body = this.findRowBody(target)) && grid.fireEvent('rowbody' + name, grid, row, e);
                    }
                }
            } else {
                grid.fireEvent('container' + name, grid, e);
            }
        }
    },


    layout: function (initial) {
        if (!this.mainBody) {
            return;
        }

        var grid = this.grid,
            gridEl = grid.getGridEl(),
            gridSize = gridEl.getSize(true),
            gridWidth = gridSize.width,
            gridHeight = gridSize.height,
            scroller = this.scroller,
            scrollStyle, headerHeight, scrollHeight;

        if (gridWidth < 20 || gridHeight < 20) {
            return;
        }

        if (grid.autoHeight) {
            scrollStyle = scroller.dom.style;
            scrollStyle.overflow = 'visible';

            if (Ext.isWebKit) {
                scrollStyle.position = 'static';
            }
        } else {
            this.el.setSize(gridWidth, gridHeight);

            headerHeight = this.mainHd.getHeight();
            scrollHeight = gridHeight - headerHeight;

            scroller.setSize(gridWidth, scrollHeight);

            if (this.innerHd) {
                this.innerHd.style.width = (gridWidth) + "px";
            }
        }

        if (this.forceFit || (initial === true && this.autoFill)) {
            if (this.lastViewWidth != gridWidth) {
                this.fitColumns(false, false);
                this.lastViewWidth = gridWidth;
            }
        } else {
            this.autoExpand();
            this.syncHeaderScroll();
        }

        this.onLayout(gridWidth, scrollHeight);
    },



    onLayout: function (vw, vh) {

    },

    onColumnWidthUpdated: function (col, w, tw) {

    },

    onAllColumnWidthsUpdated: function (ws, tw) {

    },

    onColumnHiddenUpdated: function (col, hidden, tw) {

    },

    updateColumnText: function (col, text) {

    },

    afterMove: function (colIndex) {

    },



    init: function (grid) {
        this.grid = grid;

        this.initTemplates();
        this.initData(grid.store, grid.colModel);
        this.initUI(grid);
    },


    getColumnId: function (index) {
        return this.cm.getColumnId(index);
    },


    getOffsetWidth: function () {
        return (this.cm.getTotalWidth() + this.getScrollOffset()) + 'px';
    },


    getScrollOffset: function () {
        return Ext.num(this.scrollOffset, Ext.getScrollBarWidth());
    },


    renderHeaders: function () {
        var colModel = this.cm,
            templates = this.templates,
            headerTpl = templates.hcell,
            properties = {},
            colCount = colModel.getColumnCount(),
            last = colCount - 1,
            cells = [],
            i, cssCls;

        for (i = 0; i < colCount; i++) {
            if (i == 0) {
                cssCls = 'x-grid3-cell-first ';
            } else {
                cssCls = i == last ? 'x-grid3-cell-last ' : '';
            }

            properties = {
                id: colModel.getColumnId(i),
                value: colModel.getColumnHeader(i) || '',
                style: this.getColumnStyle(i, true),
                css: cssCls,
                tooltip: this.getColumnTooltip(i)
            };

            if (colModel.config[i].align == 'right') {
                properties.istyle = 'padding-right: 16px;';
            } else {
                delete properties.istyle;
            }

            cells[i] = headerTpl.apply(properties);
        }

        return templates.header.apply({
            cells: cells.join(""),
            tstyle: String.format("width: {0};", this.getTotalWidth())
        });
    },


    getColumnTooltip: function (i) {
        var tooltip = this.cm.getColumnTooltip(i);
        if (tooltip) {
            if (Ext.QuickTips.isEnabled()) {
                return 'ext:qtip="' + tooltip + '"';
            } else {
                return 'title="' + tooltip + '"';
            }
        }

        return '';
    },


    beforeUpdate: function () {
        this.grid.stopEditing(true);
    },


    updateHeaders: function () {
        this.innerHd.firstChild.innerHTML = this.renderHeaders();

        this.updateHeaderWidth(false);
    },


    updateHeaderWidth: function (updateMain) {
        var innerHdChild = this.innerHd.firstChild,
            totalWidth = this.getTotalWidth();

        innerHdChild.style.width = this.getOffsetWidth();
        innerHdChild.firstChild.style.width = totalWidth;

        if (updateMain !== false) {
            this.mainBody.dom.style.width = totalWidth;
        }
    },


    focusRow: function (row) {
        this.focusCell(row, 0, false);
    },


    focusCell: function (row, col, hscroll) {
        this.syncFocusEl(this.ensureVisible(row, col, hscroll));

        var focusEl = this.focusEl;

        if (Ext.isGecko) {
            focusEl.focus();
        } else {
            focusEl.focus.defer(1, focusEl);
        }
    },


    resolveCell: function (row, col, hscroll) {
        if (!Ext.isNumber(row)) {
            row = row.rowIndex;
        }

        if (!this.ds) {
            return null;
        }

        if (row < 0 || row >= this.ds.getCount()) {
            return null;
        }
        col = (col !== undefined ? col : 0);

        var rowEl = this.getRow(row),
            colModel = this.cm,
            colCount = colModel.getColumnCount(),
            cellEl;

        if (!(hscroll === false && col === 0)) {
            while (col < colCount && colModel.isHidden(col)) {
                col++;
            }

            cellEl = this.getCell(row, col);
        }

        return { row: rowEl, cell: cellEl };
    },


    getResolvedXY: function (resolved) {
        if (!resolved) {
            return null;
        }

        var cell = resolved.cell,
            row = resolved.row;

        if (cell) {
            return Ext.fly(cell).getXY();
        } else {
            return [this.el.getX(), Ext.fly(row).getY()];
        }
    },


    syncFocusEl: function (row, col, hscroll) {
        var xy = row;

        if (!Ext.isArray(xy)) {
            row = Math.min(row, Math.max(0, this.getRows().length - 1));

            if (isNaN(row)) {
                return;
            }

            xy = this.getResolvedXY(this.resolveCell(row, col, hscroll));
        }

        this.focusEl.setXY(xy || this.scroller.getXY());
    },


    ensureVisible: function (row, col, hscroll) {
        var resolved = this.resolveCell(row, col, hscroll);

        if (!resolved || !resolved.row) {
            return null;
        }

        var rowEl = resolved.row,
            cellEl = resolved.cell,
            c = this.scroller.dom,
            p = rowEl,
            ctop = 0,
            stop = this.el.dom;

        while (p && p != stop) {
            ctop += p.offsetTop;
            p = p.offsetParent;
        }

        ctop -= this.mainHd.dom.offsetHeight;
        stop = parseInt(c.scrollTop, 10);

        var cbot = ctop + rowEl.offsetHeight,
            ch = c.clientHeight,
            sbot = stop + ch;


        if (ctop < stop) {
            c.scrollTop = ctop;
        } else if (cbot > sbot) {
            c.scrollTop = cbot - ch;
        }

        if (hscroll !== false) {
            var cleft = parseInt(cellEl.offsetLeft, 10),
                cright = cleft + cellEl.offsetWidth,
                sleft = parseInt(c.scrollLeft, 10),
                sright = sleft + c.clientWidth;

            if (cleft < sleft) {
                c.scrollLeft = cleft;
            } else if (cright > sright) {
                c.scrollLeft = cright - c.clientWidth;
            }
        }

        return this.getResolvedXY(resolved);
    },


    insertRows: function (dm, firstRow, lastRow, isUpdate) {
        var last = dm.getCount() - 1;
        if (!isUpdate && firstRow === 0 && lastRow >= last) {
            this.fireEvent('beforerowsinserted', this, firstRow, lastRow);
            this.refresh();
            this.fireEvent('rowsinserted', this, firstRow, lastRow);
        } else {
            if (!isUpdate) {
                this.fireEvent('beforerowsinserted', this, firstRow, lastRow);
            }
            var html = this.renderRows(firstRow, lastRow),
                before = this.getRow(firstRow);
            if (before) {
                if (firstRow === 0) {
                    Ext.fly(this.getRow(0)).removeClass(this.firstRowCls);
                }
                Ext.DomHelper.insertHtml('beforeBegin', before, html);
            } else {
                var r = this.getRow(last - 1);
                if (r) {
                    Ext.fly(r).removeClass(this.lastRowCls);
                }
                Ext.DomHelper.insertHtml('beforeEnd', this.mainBody.dom, html);
            }
            if (!isUpdate) {
                this.fireEvent('rowsinserted', this, firstRow, lastRow);
                this.processRows(firstRow);
            } else if (firstRow === 0 || firstRow >= last) {

                Ext.fly(this.getRow(firstRow)).addClass(firstRow === 0 ? this.firstRowCls : this.lastRowCls);
            }
        }
        this.syncFocusEl(firstRow);
    },


    deleteRows: function (dm, firstRow, lastRow) {
        if (dm.getRowCount() < 1) {
            this.refresh();
        } else {
            this.fireEvent('beforerowsdeleted', this, firstRow, lastRow);

            this.removeRows(firstRow, lastRow);

            this.processRows(firstRow);
            this.fireEvent('rowsdeleted', this, firstRow, lastRow);
        }
    },


    getColumnStyle: function (colIndex, isHeader) {
        var colModel = this.cm,
            colConfig = colModel.config,
            style = isHeader ? '' : colConfig[colIndex].css || '',
            align = colConfig[colIndex].align;

        style += String.format("width: {0};", this.getColumnWidth(colIndex));

        if (colModel.isHidden(colIndex)) {
            style += 'display: none; ';
        }

        if (align) {
            style += String.format("text-align: {0};", align);
        }

        return style;
    },


    getColumnWidth: function (column) {
        var columnWidth = this.cm.getColumnWidth(column),
            borderWidth = this.borderWidth;

        if (Ext.isNumber(columnWidth)) {
            if (Ext.isBorderBox || (Ext.isWebKit && !Ext.isSafari2)) {
                return columnWidth + "px";
            } else {
                return Math.max(columnWidth - borderWidth, 0) + "px";
            }
        } else {
            return columnWidth;
        }
    },


    getTotalWidth: function () {
        return this.cm.getTotalWidth() + 'px';
    },


    fitColumns: function (preventRefresh, onlyExpand, omitColumn) {
        var grid = this.grid,
            colModel = this.cm,
            totalColWidth = colModel.getTotalWidth(false),
            gridWidth = this.getGridInnerWidth(),
            extraWidth = gridWidth - totalColWidth,
            columns = [],
            extraCol = 0,
            width = 0,
            colWidth, fraction, i;


        if (gridWidth < 20 || extraWidth === 0) {
            return false;
        }

        var visibleColCount = colModel.getColumnCount(true),
            totalColCount = colModel.getColumnCount(false),
            adjCount = visibleColCount - (Ext.isNumber(omitColumn) ? 1 : 0);

        if (adjCount === 0) {
            adjCount = 1;
            omitColumn = undefined;
        }


        for (i = 0; i < totalColCount; i++) {
            if (!colModel.isFixed(i) && i !== omitColumn) {
                colWidth = colModel.getColumnWidth(i);
                columns.push(i, colWidth);

                if (!colModel.isHidden(i)) {
                    extraCol = i;
                    width += colWidth;
                }
            }
        }

        fraction = (gridWidth - colModel.getTotalWidth()) / width;

        while (columns.length) {
            colWidth = columns.pop();
            i = columns.pop();

            colModel.setColumnWidth(i, Math.max(grid.minColumnWidth, Math.floor(colWidth + colWidth * fraction)), true);
        }


        totalColWidth = colModel.getTotalWidth(false);

        if (totalColWidth > gridWidth) {
            var adjustCol = (adjCount == visibleColCount) ? extraCol : omitColumn,
                newWidth = Math.max(1, colModel.getColumnWidth(adjustCol) - (totalColWidth - gridWidth));

            colModel.setColumnWidth(adjustCol, newWidth, true);
        }

        if (preventRefresh !== true) {
            this.updateAllColumnWidths();
        }

        return true;
    },


    autoExpand: function (preventUpdate) {
        var grid = this.grid,
            colModel = this.cm,
            gridWidth = this.getGridInnerWidth(),
            totalColumnWidth = colModel.getTotalWidth(false),
            autoExpandColumn = grid.autoExpandColumn;

        if (!this.userResized && autoExpandColumn) {
            if (gridWidth != totalColumnWidth) {

                var colIndex = colModel.getIndexById(autoExpandColumn),
                    currentWidth = colModel.getColumnWidth(colIndex),
                    desiredWidth = gridWidth - totalColumnWidth + currentWidth,
                    newWidth = Math.min(Math.max(desiredWidth, grid.autoExpandMin), grid.autoExpandMax);

                if (currentWidth != newWidth) {
                    colModel.setColumnWidth(colIndex, newWidth, true);

                    if (preventUpdate !== true) {
                        this.updateColumnWidth(colIndex, newWidth);
                    }
                }
            }
        }
    },


    getGridInnerWidth: function () {
        return this.grid.getGridEl().getWidth(true) - this.getScrollOffset();
    },


    getColumnData: function () {
        var columns = [],
            colModel = this.cm,
            colCount = colModel.getColumnCount(),
            fields = this.ds.fields,
            i, name;

        for (i = 0; i < colCount; i++) {
            name = colModel.getDataIndex(i);

            columns[i] = {
                name: Ext.isDefined(name) ? name : (fields.get(i) ? fields.get(i).name : undefined),
                renderer: colModel.getRenderer(i),
                scope: colModel.getRendererScope(i),
                id: colModel.getColumnId(i),
                style: this.getColumnStyle(i)
            };
        }

        return columns;
    },


    renderRows: function (startRow, endRow) {
        var grid = this.grid,
            store = grid.store,
            stripe = grid.stripeRows,
            colModel = grid.colModel,
            colCount = colModel.getColumnCount(),
            rowCount = store.getCount(),
            records;

        if (rowCount < 1) {
            return '';
        }

        startRow = startRow || 0;
        endRow = Ext.isDefined(endRow) ? endRow : rowCount - 1;
        records = store.getRange(startRow, endRow);

        return this.doRender(this.getColumnData(), records, store, startRow, colCount, stripe);
    },


    renderBody: function () {
        var markup = this.renderRows() || '&#160;';
        return this.templates.body.apply({ rows: markup });
    },


    refreshRow: function (record) {
        var store = this.ds,
            colCount = this.cm.getColumnCount(),
            columns = this.getColumnData(),
            last = colCount - 1,
            cls = ['x-grid3-row'],
            rowParams = {
                tstyle: String.format("width: {0};", this.getTotalWidth())
            },
            colBuffer = [],
            cellTpl = this.templates.cell,
            rowIndex, row, column, meta, css, i;

        if (Ext.isNumber(record)) {
            rowIndex = record;
            record = store.getAt(rowIndex);
        } else {
            rowIndex = store.indexOf(record);
        }


        if (!record || rowIndex < 0) {
            return;
        }


        for (i = 0; i < colCount; i++) {
            column = columns[i];

            if (i == 0) {
                css = 'x-grid3-cell-first';
            } else {
                css = (i == last) ? 'x-grid3-cell-last ' : '';
            }

            meta = {
                id: column.id,
                style: column.style,
                css: css,
                attr: "",
                cellAttr: ""
            };

            meta.value = column.renderer.call(column.scope, record.data[column.name], meta, record, rowIndex, i, store);

            if (Ext.isEmpty(meta.value)) {
                meta.value = '&#160;';
            }

            if (this.markDirty && record.dirty && typeof record.modified[column.name] != 'undefined') {
                meta.css += ' x-grid3-dirty-cell';
            }

            colBuffer[i] = cellTpl.apply(meta);
        }

        row = this.getRow(rowIndex);
        row.className = '';

        if (this.grid.stripeRows && ((rowIndex + 1) % 2 === 0)) {
            cls.push('x-grid3-row-alt');
        }

        if (this.getRowClass) {
            rowParams.cols = colCount;
            cls.push(this.getRowClass(record, rowIndex, rowParams, store));
        }

        this.fly(row).addClass(cls).setStyle(rowParams.tstyle);
        rowParams.cells = colBuffer.join("");
        row.innerHTML = this.templates.rowInner.apply(rowParams);

        this.fireEvent('rowupdated', this, rowIndex, record);
    },


    refresh: function (headersToo) {
        this.fireEvent('beforerefresh', this);
        this.grid.stopEditing(true);

        var result = this.renderBody();
        this.mainBody.update(result).setWidth(this.getTotalWidth());
        if (headersToo === true) {
            this.updateHeaders();
            this.updateHeaderSortState();
        }
        this.processRows(0, true);
        this.layout();
        this.applyEmptyText();
        this.fireEvent('refresh', this);
    },


    applyEmptyText: function () {
        if (this.emptyText && !this.hasRows()) {
            this.mainBody.update('<div class="x-grid-empty">' + this.emptyText + '</div>');
        }
    },


    updateHeaderSortState: function () {
        var state = this.ds.getSortState();
        if (!state) {
            return;
        }

        if (!this.sortState || (this.sortState.field != state.field || this.sortState.direction != state.direction)) {
            this.grid.fireEvent('sortchange', this.grid, state);
        }

        this.sortState = state;

        var sortColumn = this.cm.findColumnIndex(state.field);
        if (sortColumn != -1) {
            var sortDir = state.direction;
            this.updateSortIcon(sortColumn, sortDir);
        }
    },


    clearHeaderSortState: function () {
        if (!this.sortState) {
            return;
        }
        this.grid.fireEvent('sortchange', this.grid, null);
        this.mainHd.select('td').removeClass(this.sortClasses);
        delete this.sortState;
    },


    destroy: function () {
        var me = this,
            grid = me.grid,
            gridEl = grid.getGridEl(),
            dragZone = me.dragZone,
            splitZone = me.splitZone,
            columnDrag = me.columnDrag,
            columnDrop = me.columnDrop,
            scrollToTopTask = me.scrollToTopTask,
            columnDragData,
            columnDragProxy;

        if (scrollToTopTask && scrollToTopTask.cancel) {
            scrollToTopTask.cancel();
        }

        Ext.destroyMembers(me, 'colMenu', 'hmenu');

        me.initData(null, null);
        me.purgeListeners();

        Ext.fly(me.innerHd).un("click", me.handleHdDown, me);

        if (grid.enableColumnMove) {
            columnDragData = columnDrag.dragData;
            columnDragProxy = columnDrag.proxy;
            Ext.destroy(
                columnDrag.el,
                columnDragProxy.ghost,
                columnDragProxy.el,
                columnDrop.el,
                columnDrop.proxyTop,
                columnDrop.proxyBottom,
                columnDragData.ddel,
                columnDragData.header
            );

            if (columnDragProxy.anim) {
                Ext.destroy(columnDragProxy.anim);
            }

            delete columnDragProxy.ghost;
            delete columnDragData.ddel;
            delete columnDragData.header;
            columnDrag.destroy();

            delete Ext.dd.DDM.locationCache[columnDrag.id];
            delete columnDrag._domRef;

            delete columnDrop.proxyTop;
            delete columnDrop.proxyBottom;
            columnDrop.destroy();
            delete Ext.dd.DDM.locationCache["gridHeader" + gridEl.id];
            delete columnDrop._domRef;
            delete Ext.dd.DDM.ids[columnDrop.ddGroup];
        }

        if (splitZone) {
            splitZone.destroy();
            delete splitZone._domRef;
            delete Ext.dd.DDM.ids["gridSplitters" + gridEl.id];
        }

        Ext.fly(me.innerHd).removeAllListeners();
        Ext.removeNode(me.innerHd);
        delete me.innerHd;

        Ext.destroy(
            me.el,
            me.mainWrap,
            me.mainHd,
            me.scroller,
            me.mainBody,
            me.focusEl,
            me.resizeMarker,
            me.resizeProxy,
            me.activeHdBtn,
            me._flyweight,
            dragZone,
            splitZone
        );

        delete grid.container;

        if (dragZone) {
            dragZone.destroy();
        }

        Ext.dd.DDM.currentTarget = null;
        delete Ext.dd.DDM.locationCache[gridEl.id];

        Ext.EventManager.removeResizeListener(me.onWindowResize, me);
    },


    onDenyColumnHide: function () {

    },


    render: function () {
        if (this.autoFill) {
            var ct = this.grid.ownerCt;

            if (ct && ct.getLayout()) {
                ct.on('afterlayout', function () {
                    this.fitColumns(true, true);
                    this.updateHeaders();
                    this.updateHeaderSortState();
                }, this, { single: true });
            }
        } else if (this.forceFit) {
            this.fitColumns(true, false);
        } else if (this.grid.autoExpandColumn) {
            this.autoExpand(true);
        }

        this.grid.getGridEl().dom.innerHTML = this.renderUI();

        this.afterRenderUI();
    },




    initData: function (newStore, newColModel) {
        var me = this;

        if (me.ds) {
            var oldStore = me.ds;

            oldStore.un('add', me.onAdd, me);
            oldStore.un('load', me.onLoad, me);
            oldStore.un('clear', me.onClear, me);
            oldStore.un('remove', me.onRemove, me);
            oldStore.un('update', me.onUpdate, me);
            oldStore.un('datachanged', me.onDataChange, me);

            if (oldStore !== newStore && oldStore.autoDestroy) {
                oldStore.destroy();
            }
        }

        if (newStore) {
            newStore.on({
                scope: me,
                load: me.onLoad,
                add: me.onAdd,
                remove: me.onRemove,
                update: me.onUpdate,
                clear: me.onClear,
                datachanged: me.onDataChange
            });
        }

        if (me.cm) {
            var oldColModel = me.cm;

            oldColModel.un('configchange', me.onColConfigChange, me);
            oldColModel.un('widthchange', me.onColWidthChange, me);
            oldColModel.un('headerchange', me.onHeaderChange, me);
            oldColModel.un('hiddenchange', me.onHiddenChange, me);
            oldColModel.un('columnmoved', me.onColumnMove, me);
        }

        if (newColModel) {
            delete me.lastViewWidth;

            newColModel.on({
                scope: me,
                configchange: me.onColConfigChange,
                widthchange: me.onColWidthChange,
                headerchange: me.onHeaderChange,
                hiddenchange: me.onHiddenChange,
                columnmoved: me.onColumnMove
            });
        }

        me.ds = newStore;
        me.cm = newColModel;
    },


    onDataChange: function () {
        this.refresh(true);
        this.updateHeaderSortState();
        this.syncFocusEl(0);
    },


    onClear: function () {
        this.refresh();
        this.syncFocusEl(0);
    },


    onUpdate: function (store, record) {
        this.refreshRow(record);
    },


    onAdd: function (store, records, index) {
        this.insertRows(store, index, index + (records.length - 1));
    },


    onRemove: function (store, record, index, isUpdate) {
        if (isUpdate !== true) {
            this.fireEvent('beforerowremoved', this, index, record);
        }

        this.removeRow(index);

        if (isUpdate !== true) {
            this.processRows(index);
            this.applyEmptyText();
            this.fireEvent('rowremoved', this, index, record);
        }
    },


    onLoad: function () {
        if (Ext.isGecko) {
            if (!this.scrollToTopTask) {
                this.scrollToTopTask = new Ext.util.DelayedTask(this.scrollToTop, this);
            }
            this.scrollToTopTask.delay(1);
        } else {
            this.scrollToTop();
        }
    },


    onColWidthChange: function (cm, col, width) {
        this.updateColumnWidth(col, width);
    },


    onHeaderChange: function (cm, col, text) {
        this.updateHeaders();
    },


    onHiddenChange: function (cm, col, hidden) {
        this.updateColumnHidden(col, hidden);
    },


    onColumnMove: function (cm, oldIndex, newIndex) {
        this.indexMap = null;
        this.refresh(true);
        this.restoreScroll(this.getScrollState());

        this.afterMove(newIndex);
        this.grid.fireEvent('columnmove', oldIndex, newIndex);
    },


    onColConfigChange: function () {
        delete this.lastViewWidth;
        this.indexMap = null;
        this.refresh(true);
    },



    initUI: function (grid) {
        grid.on('headerclick', this.onHeaderClick, this);
    },


    initEvents: Ext.emptyFn,


    onHeaderClick: function (g, index) {
        if (this.headersDisabled || !this.cm.isSortable(index)) {
            return;
        }
        g.stopEditing(true);
        g.store.sort(this.cm.getDataIndex(index));
    },


    onRowOver: function (e, target) {
        var row = this.findRowIndex(target);

        if (row !== false) {
            this.addRowClass(row, this.rowOverCls);
        }
    },


    onRowOut: function (e, target) {
        var row = this.findRowIndex(target);

        if (row !== false && !e.within(this.getRow(row), true)) {
            this.removeRowClass(row, this.rowOverCls);
        }
    },


    onRowSelect: function (row) {
        this.addRowClass(row, this.selectedRowClass);
    },


    onRowDeselect: function (row) {
        this.removeRowClass(row, this.selectedRowClass);
    },


    onCellSelect: function (row, col) {
        var cell = this.getCell(row, col);
        if (cell) {
            this.fly(cell).addClass('x-grid3-cell-selected');
        }
    },


    onCellDeselect: function (row, col) {
        var cell = this.getCell(row, col);
        if (cell) {
            this.fly(cell).removeClass('x-grid3-cell-selected');
        }
    },


    handleWheel: function (e) {
        e.stopPropagation();
    },


    onColumnSplitterMoved: function (cellIndex, width) {
        this.userResized = true;
        this.grid.colModel.setColumnWidth(cellIndex, width, true);

        if (this.forceFit) {
            this.fitColumns(true, false, cellIndex);
            this.updateAllColumnWidths();
        } else {
            this.updateColumnWidth(cellIndex, width);
            this.syncHeaderScroll();
        }

        this.grid.fireEvent('columnresize', cellIndex, width);
    },


    beforeColMenuShow: function () {
        var colModel = this.cm,
            colCount = colModel.getColumnCount(),
            colMenu = this.colMenu,
            i;

        colMenu.removeAll();

        for (i = 0; i < colCount; i++) {
            if (colModel.config[i].hideable !== false) {
                colMenu.add(new Ext.menu.CheckItem({
                    text: colModel.getColumnHeader(i),
                    itemId: 'col-' + colModel.getColumnId(i),
                    checked: !colModel.isHidden(i),
                    disabled: colModel.config[i].hideable === false,
                    hideOnClick: false
                }));
            }
        }
    },


    handleHdMenuClick: function (item) {
        var store = this.ds,
            dataIndex = this.cm.getDataIndex(this.hdCtxIndex);

        switch (item.getItemId()) {
            case 'asc':
                store.sort(dataIndex, 'ASC');
                break;
            case 'desc':
                store.sort(dataIndex, 'DESC');
                break;
            default:
                this.handleHdMenuClickDefault(item);
        }
        return true;
    },


    handleHdMenuClickDefault: function (item) {
        var colModel = this.cm,
            itemId = item.getItemId(),
            index = colModel.getIndexById(itemId.substr(4));

        if (index != -1) {
            if (item.checked && colModel.getColumnsBy(this.isHideableColumn, this).length <= 1) {
                this.onDenyColumnHide();
                return;
            }
            colModel.setHidden(index, item.checked);
        }
    },


    handleHdDown: function (e, target) {
        if (Ext.fly(target).hasClass('x-grid3-hd-btn')) {
            e.stopEvent();

            var colModel = this.cm,
                header = this.findHeaderCell(target),
                index = this.getCellIndex(header),
                sortable = colModel.isSortable(index),
                menu = this.hmenu,
                menuItems = menu.items,
                menuCls = this.headerMenuOpenCls;

            this.hdCtxIndex = index;

            Ext.fly(header).addClass(menuCls);
            menuItems.get('asc').setDisabled(!sortable);
            menuItems.get('desc').setDisabled(!sortable);

            menu.on('hide', function () {
                Ext.fly(header).removeClass(menuCls);
            }, this, { single: true });

            menu.show(target, 'tl-bl?');
        }
    },


    handleHdMove: function (e) {
        var header = this.findHeaderCell(this.activeHdRef);

        if (header && !this.headersDisabled) {
            var handleWidth = this.splitHandleWidth || 5,
                activeRegion = this.activeHdRegion,
                headerStyle = header.style,
                colModel = this.cm,
                cursor = '',
                pageX = e.getPageX();

            if (this.grid.enableColumnResize !== false) {
                var activeHeaderIndex = this.activeHdIndex,
                    previousVisible = this.getPreviousVisible(activeHeaderIndex),
                    currentResizable = colModel.isResizable(activeHeaderIndex),
                    previousResizable = previousVisible && colModel.isResizable(previousVisible),
                    inLeftResizer = pageX - activeRegion.left <= handleWidth,
                    inRightResizer = activeRegion.right - pageX <= (!this.activeHdBtn ? handleWidth : 2);

                if (inLeftResizer && previousResizable) {
                    cursor = Ext.isAir ? 'move' : Ext.isWebKit ? 'e-resize' : 'col-resize';
                } else if (inRightResizer && currentResizable) {
                    cursor = Ext.isAir ? 'move' : Ext.isWebKit ? 'w-resize' : 'col-resize';
                }
            }

            headerStyle.cursor = cursor;
        }
    },


    getPreviousVisible: function (index) {
        while (index > 0) {
            if (!this.cm.isHidden(index - 1)) {
                return index;
            }
            index--;
        }
        return undefined;
    },


    handleHdOver: function (e, target) {
        var header = this.findHeaderCell(target);

        if (header && !this.headersDisabled) {
            var fly = this.fly(header);

            this.activeHdRef = target;
            this.activeHdIndex = this.getCellIndex(header);
            this.activeHdRegion = fly.getRegion();

            if (!this.isMenuDisabled(this.activeHdIndex, fly)) {
                fly.addClass('x-grid3-hd-over');
                this.activeHdBtn = fly.child('.x-grid3-hd-btn');

                if (this.activeHdBtn) {
                    this.activeHdBtn.dom.style.height = (header.firstChild.offsetHeight - 1) + 'px';
                }
            }
        }
    },


    handleHdOut: function (e, target) {
        var header = this.findHeaderCell(target);

        if (header && (!Ext.isIE || !e.within(header, true))) {
            this.activeHdRef = null;
            this.fly(header).removeClass('x-grid3-hd-over');
            header.style.cursor = '';
        }
    },


    isMenuDisabled: function (cellIndex, el) {
        return this.cm.isMenuDisabled(cellIndex);
    },


    hasRows: function () {
        var fc = this.mainBody.dom.firstChild;
        return fc && fc.nodeType == 1 && fc.className != 'x-grid-empty';
    },


    isHideableColumn: function (c) {
        return !c.hidden;
    },


    bind: function (d, c) {
        this.initData(d, c);
    }
});




Ext.grid.GridView.SplitDragZone = Ext.extend(Ext.dd.DDProxy, {

    constructor: function (grid, hd) {
        this.grid = grid;
        this.view = grid.getView();
        this.marker = this.view.resizeMarker;
        this.proxy = this.view.resizeProxy;
        Ext.grid.GridView.SplitDragZone.superclass.constructor.call(this, hd,
            'gridSplitters' + this.grid.getGridEl().id, {
                dragElId: Ext.id(this.proxy.dom), resizeFrame: false
            });
        this.scroll = false;
        this.hw = this.view.splitHandleWidth || 5;
    },

    b4StartDrag: function (x, y) {
        this.dragHeadersDisabled = this.view.headersDisabled;
        this.view.headersDisabled = true;
        var h = this.view.mainWrap.getHeight();
        this.marker.setHeight(h);
        this.marker.show();
        this.marker.alignTo(this.view.getHeaderCell(this.cellIndex), 'tl-tl', [-2, 0]);
        this.proxy.setHeight(h);
        var w = this.cm.getColumnWidth(this.cellIndex),
            minw = Math.max(w - this.grid.minColumnWidth, 0);
        this.resetConstraints();
        this.setXConstraint(minw, 1000);
        this.setYConstraint(0, 0);
        this.minX = x - minw;
        this.maxX = x + 1000;
        this.startPos = x;
        Ext.dd.DDProxy.prototype.b4StartDrag.call(this, x, y);
    },

    allowHeaderDrag: function (e) {
        return true;
    },

    handleMouseDown: function (e) {
        var t = this.view.findHeaderCell(e.getTarget());
        if (t && this.allowHeaderDrag(e)) {
            var xy = this.view.fly(t).getXY(),
                x = xy[0],
                exy = e.getXY(),
                ex = exy[0],
                w = t.offsetWidth,
                adjust = false;

            if ((ex - x) <= this.hw) {
                adjust = -1;
            } else if ((x + w) - ex <= this.hw) {
                adjust = 0;
            }
            if (adjust !== false) {
                this.cm = this.grid.colModel;
                var ci = this.view.getCellIndex(t);
                if (adjust == -1) {
                    if (ci + adjust < 0) {
                        return;
                    }
                    while (this.cm.isHidden(ci + adjust)) {
                        --adjust;
                        if (ci + adjust < 0) {
                            return;
                        }
                    }
                }
                this.cellIndex = ci + adjust;
                this.split = t.dom;
                if (this.cm.isResizable(this.cellIndex) && !this.cm.isFixed(this.cellIndex)) {
                    Ext.grid.GridView.SplitDragZone.superclass.handleMouseDown.apply(this, arguments);
                }
            } else if (this.view.columnDrag) {
                this.view.columnDrag.callHandleMouseDown(e);
            }
        }
    },

    endDrag: function (e) {
        this.marker.hide();
        var v = this.view,
            endX = Math.max(this.minX, e.getPageX()),
            diff = endX - this.startPos,
            disabled = this.dragHeadersDisabled;

        v.onColumnSplitterMoved(this.cellIndex, this.cm.getColumnWidth(this.cellIndex) + diff);
        setTimeout(function () {
            v.headersDisabled = disabled;
        }, 50);
    },

    autoOffset: function () {
        this.setDelta(0, 0);
    }
});

Ext.grid.PivotGridView = Ext.extend(Ext.grid.GridView, {


    colHeaderCellCls: 'grid-hd-group-cell',


    title: '',




    getColumnHeaders: function () {
        return this.grid.topAxis.buildHeaders(); ;
    },


    getRowHeaders: function () {
        return this.grid.leftAxis.buildHeaders();
    },


    renderRows: function (startRow, endRow) {
        var grid = this.grid,
            rows = grid.extractData(),
            rowCount = rows.length,
            templates = this.templates,
            renderer = grid.renderer,
            hasRenderer = typeof renderer == 'function',
            getCellCls = this.getCellCls,
            hasGetCellCls = typeof getCellCls == 'function',
            cellTemplate = templates.cell,
            rowTemplate = templates.row,
            rowBuffer = [],
            meta = {},
            tstyle = 'width:' + this.getGridInnerWidth() + 'px;',
            colBuffer, column, i;

        startRow = startRow || 0;
        endRow = Ext.isDefined(endRow) ? endRow : rowCount - 1;

        for (i = 0; i < rowCount; i++) {
            row = rows[i];
            colCount = row.length;
            colBuffer = [];

            rowIndex = startRow + i;


            for (j = 0; j < colCount; j++) {
                cell = row[j];

                meta.css = j === 0 ? 'x-grid3-cell-first ' : (j == (colCount - 1) ? 'x-grid3-cell-last ' : '');
                meta.attr = meta.cellAttr = '';
                meta.value = cell;

                if (Ext.isEmpty(meta.value)) {
                    meta.value = '&#160;';
                }

                if (hasRenderer) {
                    meta.value = renderer(meta.value);
                }

                if (hasGetCellCls) {
                    meta.css += getCellCls(meta.value) + ' ';
                }

                colBuffer[colBuffer.length] = cellTemplate.apply(meta);
            }

            rowBuffer[rowBuffer.length] = rowTemplate.apply({
                tstyle: tstyle,
                cols: colCount,
                cells: colBuffer.join(""),
                alt: ''
            });
        }

        return rowBuffer.join("");
    },


    masterTpl: new Ext.Template(
        '<div class="x-grid3 x-pivotgrid" hidefocus="true">',
            '<div class="x-grid3-viewport">',
                '<div class="x-grid3-header">',
                    '<div class="x-grid3-header-title"><span>{title}</span></div>',
                    '<div class="x-grid3-header-inner">',
                        '<div class="x-grid3-header-offset" style="{ostyle}"></div>',
                    '</div>',
                    '<div class="x-clear"></div>',
                '</div>',
                '<div class="x-grid3-scroller">',
                    '<div class="x-grid3-row-headers"></div>',
                    '<div class="x-grid3-body" style="{bstyle}">{body}</div>',
                    '<a href="#" class="x-grid3-focus" tabIndex="-1"></a>',
                '</div>',
            '</div>',
            '<div class="x-grid3-resize-marker">&#160;</div>',
            '<div class="x-grid3-resize-proxy">&#160;</div>',
        '</div>'
    ),


    initTemplates: function () {
        Ext.grid.PivotGridView.superclass.initTemplates.apply(this, arguments);

        var templates = this.templates || {};
        if (!templates.gcell) {
            templates.gcell = new Ext.XTemplate(
                '<td class="x-grid3-hd x-grid3-gcell x-grid3-td-{id} ux-grid-hd-group-row-{row} ' + this.colHeaderCellCls + '" style="{style}">',
                    '<div {tooltip} class="x-grid3-hd-inner x-grid3-hd-{id}" unselectable="on" style="{istyle}">',
                        this.grid.enableHdMenu ? '<a class="x-grid3-hd-btn" href="#"></a>' : '', '{value}',
                    '</div>',
                '</td>'
            );
        }

        this.templates = templates;
        this.hrowRe = new RegExp("ux-grid-hd-group-row-(\\d+)", "");
    },


    initElements: function () {
        Ext.grid.PivotGridView.superclass.initElements.apply(this, arguments);


        this.rowHeadersEl = new Ext.Element(this.scroller.child('div.x-grid3-row-headers'));


        this.headerTitleEl = new Ext.Element(this.mainHd.child('div.x-grid3-header-title'));
    },


    getGridInnerWidth: function () {
        var previousWidth = Ext.grid.PivotGridView.superclass.getGridInnerWidth.apply(this, arguments);

        return previousWidth - this.getTotalRowHeaderWidth();
    },


    getTotalRowHeaderWidth: function () {
        var headers = this.getRowHeaders(),
            length = headers.length,
            total = 0,
            i;

        for (i = 0; i < length; i++) {
            total += headers[i].width;
        }

        return total;
    },


    getTotalColumnHeaderHeight: function () {
        return this.getColumnHeaders().length * 21;
    },


    renderUI: function () {
        var templates = this.templates,
            innerWidth = this.getGridInnerWidth();

        return templates.master.apply({
            body: templates.body.apply({ rows: '&#160;' }),
            ostyle: 'width:' + innerWidth + 'px',
            bstyle: 'width:' + innerWidth + 'px'
        });
    },


    onLayout: function (width, height) {
        Ext.grid.PivotGridView.superclass.onLayout.apply(this, arguments);

        var width = this.getGridInnerWidth();

        this.resizeColumnHeaders(width);
        this.resizeAllRows(width);
    },


    refresh: function (headersToo) {
        this.fireEvent('beforerefresh', this);
        this.grid.stopEditing(true);

        var result = this.renderBody();
        this.mainBody.update(result).setWidth(this.getGridInnerWidth());
        if (headersToo === true) {
            this.updateHeaders();
            this.updateHeaderSortState();
        }
        this.processRows(0, true);
        this.layout();
        this.applyEmptyText();
        this.fireEvent('refresh', this);
    },


    renderHeaders: Ext.emptyFn,


    fitColumns: Ext.emptyFn,


    resizeColumnHeaders: function (width) {
        var topAxis = this.grid.topAxis;

        if (topAxis.rendered) {
            topAxis.el.setWidth(width);
        }
    },


    resizeRowHeaders: function () {
        var rowHeaderWidth = this.getTotalRowHeaderWidth(),
            marginStyle = String.format("margin-left: {0}px;", rowHeaderWidth);

        this.rowHeadersEl.setWidth(rowHeaderWidth);
        this.mainBody.applyStyles(marginStyle);
        Ext.fly(this.innerHd).applyStyles(marginStyle);

        this.headerTitleEl.setWidth(rowHeaderWidth);
        this.headerTitleEl.setHeight(this.getTotalColumnHeaderHeight());
    },


    resizeAllRows: function (width) {
        var rows = this.getRows(),
            length = rows.length,
            i;

        for (i = 0; i < length; i++) {
            Ext.fly(rows[i]).setWidth(width);
            Ext.fly(rows[i]).child('table').setWidth(width);
        }
    },


    updateHeaders: function () {
        this.renderGroupRowHeaders();
        this.renderGroupColumnHeaders();
    },


    renderGroupRowHeaders: function () {
        var leftAxis = this.grid.leftAxis;

        this.resizeRowHeaders();
        leftAxis.rendered = false;
        leftAxis.render(this.rowHeadersEl);

        this.setTitle(this.title);
    },


    setTitle: function (title) {
        this.headerTitleEl.child('span').dom.innerHTML = title;
    },


    renderGroupColumnHeaders: function () {
        var topAxis = this.grid.topAxis;

        topAxis.rendered = false;
        topAxis.render(this.innerHd.firstChild);
    },


    isMenuDisabled: function (cellIndex, el) {
        return true;
    }
});
Ext.grid.PivotAxis = Ext.extend(Ext.Component, {

    orientation: 'horizontal',


    defaultHeaderWidth: 80,


    paddingWidth: 7,


    setDimensions: function (dimensions) {
        this.dimensions = dimensions;
    },


    onRender: function (ct, position) {
        var rows = this.orientation == 'horizontal'
                 ? this.renderHorizontalRows()
                 : this.renderVerticalRows();

        this.el = Ext.DomHelper.overwrite(ct.dom, { tag: 'table', cn: rows }, true);
    },


    renderHorizontalRows: function () {
        var headers = this.buildHeaders(),
            rowCount = headers.length,
            rows = [],
            cells, cols, colCount, i, j;

        for (i = 0; i < rowCount; i++) {
            cells = [];
            cols = headers[i].items;
            colCount = cols.length;

            for (j = 0; j < colCount; j++) {
                cells.push({
                    tag: 'td',
                    html: cols[j].header,
                    colspan: cols[j].span
                });
            }

            rows[i] = {
                tag: 'tr',
                cn: cells
            };
        }

        return rows;
    },


    renderVerticalRows: function () {
        var headers = this.buildHeaders(),
            colCount = headers.length,
            rowCells = [],
            rows = [],
            rowCount, col, row, colWidth, i, j;

        for (i = 0; i < colCount; i++) {
            col = headers[i];
            colWidth = col.width || 80;
            rowCount = col.items.length;

            for (j = 0; j < rowCount; j++) {
                row = col.items[j];

                rowCells[row.start] = rowCells[row.start] || [];
                rowCells[row.start].push({
                    tag: 'td',
                    html: row.header,
                    rowspan: row.span,
                    width: Ext.isBorderBox ? colWidth : colWidth - this.paddingWidth
                });
            }
        }

        rowCount = rowCells.length;
        for (i = 0; i < rowCount; i++) {
            rows[i] = {
                tag: 'tr',
                cn: rowCells[i]
            };
        }

        return rows;
    },


    getTuples: function () {
        var newStore = new Ext.data.Store({});

        newStore.data = this.store.data.clone();
        newStore.fields = this.store.fields;

        var sorters = [],
            dimensions = this.dimensions,
            length = dimensions.length,
            i;

        for (i = 0; i < length; i++) {
            sorters.push({
                field: dimensions[i].dataIndex,
                direction: dimensions[i].direction || 'ASC'
            });
        }

        newStore.sort(sorters);

        var records = newStore.data.items,
            hashes = [],
            tuples = [],
            recData, hash, info, data, key;

        length = records.length;

        for (i = 0; i < length; i++) {
            info = this.getRecordInfo(records[i]);
            data = info.data;
            hash = "";

            for (key in data) {
                hash += data[key] + '---';
            }

            if (hashes.indexOf(hash) == -1) {
                hashes.push(hash);
                tuples.push(info);
            }
        }

        newStore.destroy();

        return tuples;
    },


    getRecordInfo: function (record) {
        var dimensions = this.dimensions,
            length = dimensions.length,
            data = {},
            dimension, dataIndex, i;


        for (i = 0; i < length; i++) {
            dimension = dimensions[i];
            dataIndex = dimension.dataIndex;

            data[dataIndex] = record.get(dataIndex);
        }



        var createMatcherFunction = function (data) {
            return function (record) {
                for (var dataIndex in data) {
                    if (record.get(dataIndex) != data[dataIndex]) {
                        return false;
                    }
                }

                return true;
            };
        };

        return {
            data: data,
            matcher: createMatcherFunction(data)
        };
    },


    buildHeaders: function () {
        var tuples = this.getTuples(),
            rowCount = tuples.length,
            dimensions = this.dimensions,
            colCount = dimensions.length,
            headers = [],
            tuple, rows, currentHeader, previousHeader, span, start, isLast, changed, i, j;

        for (i = 0; i < colCount; i++) {
            dimension = dimensions[i];
            rows = [];
            span = 0;
            start = 0;

            for (j = 0; j < rowCount; j++) {
                tuple = tuples[j];
                isLast = j == (rowCount - 1);
                currentHeader = tuple.data[dimension.dataIndex];


                changed = previousHeader != undefined && previousHeader != currentHeader;
                if (i > 0 && j > 0) {
                    changed = changed || tuple.data[dimensions[i - 1].dataIndex] != tuples[j - 1].data[dimensions[i - 1].dataIndex];
                }

                if (changed) {
                    rows.push({
                        header: previousHeader,
                        span: span,
                        start: start
                    });

                    start += span;
                    span = 0;
                }

                if (isLast) {
                    rows.push({
                        header: currentHeader,
                        span: span + 1,
                        start: start
                    });

                    start += span;
                    span = 0;
                }

                previousHeader = currentHeader;
                span++;
            }

            headers.push({
                items: rows,
                width: dimension.width || this.defaultHeaderWidth
            });

            previousHeader = undefined;
        }

        return headers;
    }
});


Ext.grid.HeaderDragZone = Ext.extend(Ext.dd.DragZone, {
    maxDragWidth: 120,

    constructor: function (grid, hd, hd2) {
        this.grid = grid;
        this.view = grid.getView();
        this.ddGroup = "gridHeader" + this.grid.getGridEl().id;
        Ext.grid.HeaderDragZone.superclass.constructor.call(this, hd);
        if (hd2) {
            this.setHandleElId(Ext.id(hd));
            this.setOuterHandleElId(Ext.id(hd2));
        }
        this.scroll = false;
    },

    getDragData: function (e) {
        var t = Ext.lib.Event.getTarget(e),
            h = this.view.findHeaderCell(t);
        if (h) {
            return { ddel: h.firstChild, header: h };
        }
        return false;
    },

    onInitDrag: function (e) {

        this.dragHeadersDisabled = this.view.headersDisabled;
        this.view.headersDisabled = true;
        var clone = this.dragData.ddel.cloneNode(true);
        clone.id = Ext.id();
        clone.style.width = Math.min(this.dragData.header.offsetWidth, this.maxDragWidth) + "px";
        this.proxy.update(clone);
        return true;
    },

    afterValidDrop: function () {
        this.completeDrop();
    },

    afterInvalidDrop: function () {
        this.completeDrop();
    },

    completeDrop: function () {
        var v = this.view,
            disabled = this.dragHeadersDisabled;
        setTimeout(function () {
            v.headersDisabled = disabled;
        }, 50);
    }
});



Ext.grid.HeaderDropZone = Ext.extend(Ext.dd.DropZone, {
    proxyOffsets: [-4, -9],
    fly: Ext.Element.fly,

    constructor: function (grid, hd, hd2) {
        this.grid = grid;
        this.view = grid.getView();

        this.proxyTop = Ext.DomHelper.append(document.body, {
            cls: "col-move-top", html: "&#160;"
        }, true);
        this.proxyBottom = Ext.DomHelper.append(document.body, {
            cls: "col-move-bottom", html: "&#160;"
        }, true);
        this.proxyTop.hide = this.proxyBottom.hide = function () {
            this.setLeftTop(-100, -100);
            this.setStyle("visibility", "hidden");
        };
        this.ddGroup = "gridHeader" + this.grid.getGridEl().id;


        Ext.grid.HeaderDropZone.superclass.constructor.call(this, grid.getGridEl().dom);
    },

    getTargetFromEvent: function (e) {
        var t = Ext.lib.Event.getTarget(e),
            cindex = this.view.findCellIndex(t);
        if (cindex !== false) {
            return this.view.getHeaderCell(cindex);
        }
    },

    nextVisible: function (h) {
        var v = this.view, cm = this.grid.colModel;
        h = h.nextSibling;
        while (h) {
            if (!cm.isHidden(v.getCellIndex(h))) {
                return h;
            }
            h = h.nextSibling;
        }
        return null;
    },

    prevVisible: function (h) {
        var v = this.view, cm = this.grid.colModel;
        h = h.prevSibling;
        while (h) {
            if (!cm.isHidden(v.getCellIndex(h))) {
                return h;
            }
            h = h.prevSibling;
        }
        return null;
    },

    positionIndicator: function (h, n, e) {
        var x = Ext.lib.Event.getPageX(e),
            r = Ext.lib.Dom.getRegion(n.firstChild),
            px,
            pt,
            py = r.top + this.proxyOffsets[1];
        if ((r.right - x) <= (r.right - r.left) / 2) {
            px = r.right + this.view.borderWidth;
            pt = "after";
        } else {
            px = r.left;
            pt = "before";
        }

        if (this.grid.colModel.isFixed(this.view.getCellIndex(n))) {
            return false;
        }

        px += this.proxyOffsets[0];
        this.proxyTop.setLeftTop(px, py);
        this.proxyTop.show();
        if (!this.bottomOffset) {
            this.bottomOffset = this.view.mainHd.getHeight();
        }
        this.proxyBottom.setLeftTop(px, py + this.proxyTop.dom.offsetHeight + this.bottomOffset);
        this.proxyBottom.show();
        return pt;
    },

    onNodeEnter: function (n, dd, e, data) {
        if (data.header != n) {
            this.positionIndicator(data.header, n, e);
        }
    },

    onNodeOver: function (n, dd, e, data) {
        var result = false;
        if (data.header != n) {
            result = this.positionIndicator(data.header, n, e);
        }
        if (!result) {
            this.proxyTop.hide();
            this.proxyBottom.hide();
        }
        return result ? this.dropAllowed : this.dropNotAllowed;
    },

    onNodeOut: function (n, dd, e, data) {
        this.proxyTop.hide();
        this.proxyBottom.hide();
    },

    onNodeDrop: function (n, dd, e, data) {
        var h = data.header;
        if (h != n) {
            var cm = this.grid.colModel,
                x = Ext.lib.Event.getPageX(e),
                r = Ext.lib.Dom.getRegion(n.firstChild),
                pt = (r.right - x) <= ((r.right - r.left) / 2) ? "after" : "before",
                oldIndex = this.view.getCellIndex(h),
                newIndex = this.view.getCellIndex(n);
            if (pt == "after") {
                newIndex++;
            }
            if (oldIndex < newIndex) {
                newIndex--;
            }
            cm.moveColumn(oldIndex, newIndex);
            return true;
        }
        return false;
    }
});

Ext.grid.GridView.ColumnDragZone = Ext.extend(Ext.grid.HeaderDragZone, {

    constructor: function (grid, hd) {
        Ext.grid.GridView.ColumnDragZone.superclass.constructor.call(this, grid, hd, null);
        this.proxy.el.addClass('x-grid3-col-dd');
    },

    handleMouseDown: function (e) {
    },

    callHandleMouseDown: function (e) {
        Ext.grid.GridView.ColumnDragZone.superclass.handleMouseDown.call(this, e);
    }
});

Ext.grid.SplitDragZone = Ext.extend(Ext.dd.DDProxy, {
    fly: Ext.Element.fly,

    constructor: function (grid, hd, hd2) {
        this.grid = grid;
        this.view = grid.getView();
        this.proxy = this.view.resizeProxy;
        Ext.grid.SplitDragZone.superclass.constructor.call(this, hd,
            "gridSplitters" + this.grid.getGridEl().id, {
                dragElId: Ext.id(this.proxy.dom), resizeFrame: false
            });
        this.setHandleElId(Ext.id(hd));
        this.setOuterHandleElId(Ext.id(hd2));
        this.scroll = false;
    },

    b4StartDrag: function (x, y) {
        this.view.headersDisabled = true;
        this.proxy.setHeight(this.view.mainWrap.getHeight());
        var w = this.cm.getColumnWidth(this.cellIndex);
        var minw = Math.max(w - this.grid.minColumnWidth, 0);
        this.resetConstraints();
        this.setXConstraint(minw, 1000);
        this.setYConstraint(0, 0);
        this.minX = x - minw;
        this.maxX = x + 1000;
        this.startPos = x;
        Ext.dd.DDProxy.prototype.b4StartDrag.call(this, x, y);
    },


    handleMouseDown: function (e) {
        var ev = Ext.EventObject.setEvent(e);
        var t = this.fly(ev.getTarget());
        if (t.hasClass("x-grid-split")) {
            this.cellIndex = this.view.getCellIndex(t.dom);
            this.split = t.dom;
            this.cm = this.grid.colModel;
            if (this.cm.isResizable(this.cellIndex) && !this.cm.isFixed(this.cellIndex)) {
                Ext.grid.SplitDragZone.superclass.handleMouseDown.apply(this, arguments);
            }
        }
    },

    endDrag: function (e) {
        this.view.headersDisabled = false;
        var endX = Math.max(this.minX, Ext.lib.Event.getPageX(e));
        var diff = endX - this.startPos;
        this.view.onColumnSplitterMoved(this.cellIndex, this.cm.getColumnWidth(this.cellIndex) + diff);
    },

    autoOffset: function () {
        this.setDelta(0, 0);
    }
});
Ext.grid.GridDragZone = function (grid, config) {
    this.view = grid.getView();
    Ext.grid.GridDragZone.superclass.constructor.call(this, this.view.mainBody.dom, config);
    this.scroll = false;
    this.grid = grid;
    this.ddel = document.createElement('div');
    this.ddel.className = 'x-grid-dd-wrap';
};

Ext.extend(Ext.grid.GridDragZone, Ext.dd.DragZone, {
    ddGroup: "GridDD",


    getDragData: function (e) {
        var t = Ext.lib.Event.getTarget(e);
        var rowIndex = this.view.findRowIndex(t);
        if (rowIndex !== false) {
            var sm = this.grid.selModel;
            if (!sm.isSelected(rowIndex) || e.hasModifier()) {
                sm.handleMouseDown(this.grid, rowIndex, e);
            }
            return { grid: this.grid, ddel: this.ddel, rowIndex: rowIndex, selections: sm.getSelections() };
        }
        return false;
    },


    onInitDrag: function (e) {
        var data = this.dragData;
        this.ddel.innerHTML = this.grid.getDragDropText();
        this.proxy.update(this.ddel);

    },


    afterRepair: function () {
        this.dragging = false;
    },


    getRepairXY: function (e, data) {
        return false;
    },

    onEndDrag: function (data, e) {

    },

    onValidDrop: function (dd, e, id) {

        this.hideProxy();
    },

    beforeInvalidDrop: function (e, id) {

    }
});

Ext.grid.ColumnModel = Ext.extend(Ext.util.Observable, {

    defaultWidth: 100,


    defaultSortable: false,





    constructor: function (config) {

        if (config.columns) {
            Ext.apply(this, config);
            this.setConfig(config.columns, true);
        } else {
            this.setConfig(config, true);
        }

        this.addEvents(

	        "widthchange",


	        "headerchange",


	        "hiddenchange",


	        "columnmoved",


	        "configchange"
	    );

        Ext.grid.ColumnModel.superclass.constructor.call(this);
    },


    getColumnId: function (index) {
        return this.config[index].id;
    },

    getColumnAt: function (index) {
        return this.config[index];
    },


    setConfig: function (config, initial) {
        var i, c, len;

        if (!initial) {
            delete this.totalWidth;

            for (i = 0, len = this.config.length; i < len; i++) {
                c = this.config[i];

                if (c.setEditor) {

                    c.setEditor(null);
                }
            }
        }


        this.defaults = Ext.apply({
            width: this.defaultWidth,
            sortable: this.defaultSortable
        }, this.defaults);

        this.config = config;
        this.lookup = {};

        for (i = 0, len = config.length; i < len; i++) {
            c = Ext.applyIf(config[i], this.defaults);


            if (Ext.isEmpty(c.id)) {
                c.id = i;
            }

            if (!c.isColumn) {
                var Cls = Ext.grid.Column.types[c.xtype || 'gridcolumn'];
                c = new Cls(c);
                config[i] = c;
            }

            this.lookup[c.id] = c;
        }

        if (!initial) {
            this.fireEvent('configchange', this);
        }
    },


    getColumnById: function (id) {
        return this.lookup[id];
    },


    getIndexById: function (id) {
        for (var i = 0, len = this.config.length; i < len; i++) {
            if (this.config[i].id == id) {
                return i;
            }
        }
        return -1;
    },


    moveColumn: function (oldIndex, newIndex) {
        var config = this.config,
            c = config[oldIndex];

        config.splice(oldIndex, 1);
        config.splice(newIndex, 0, c);
        this.dataMap = null;
        this.fireEvent("columnmoved", this, oldIndex, newIndex);
    },


    getColumnCount: function (visibleOnly) {
        var length = this.config.length,
            c = 0,
            i;

        if (visibleOnly === true) {
            for (i = 0; i < length; i++) {
                if (!this.isHidden(i)) {
                    c++;
                }
            }

            return c;
        }

        return length;
    },


    getColumnsBy: function (fn, scope) {
        var config = this.config,
            length = config.length,
            result = [],
            i, c;

        for (i = 0; i < length; i++) {
            c = config[i];

            if (fn.call(scope || this, c, i) === true) {
                result[result.length] = c;
            }
        }

        return result;
    },


    isSortable: function (col) {
        return !!this.config[col].sortable;
    },


    isMenuDisabled: function (col) {
        return !!this.config[col].menuDisabled;
    },


    getRenderer: function (col) {
        return this.config[col].renderer || Ext.grid.ColumnModel.defaultRenderer;
    },

    getRendererScope: function (col) {
        return this.config[col].scope;
    },


    setRenderer: function (col, fn) {
        this.config[col].renderer = fn;
    },


    getColumnWidth: function (col) {
        var width = this.config[col].width;
        if (typeof width != 'number') {
            width = this.defaultWidth;
        }
        return width;
    },


    setColumnWidth: function (col, width, suppressEvent) {
        this.config[col].width = width;
        this.totalWidth = null;

        if (!suppressEvent) {
            this.fireEvent("widthchange", this, col, width);
        }
    },


    getTotalWidth: function (includeHidden) {
        if (!this.totalWidth) {
            this.totalWidth = 0;
            for (var i = 0, len = this.config.length; i < len; i++) {
                if (includeHidden || !this.isHidden(i)) {
                    this.totalWidth += this.getColumnWidth(i);
                }
            }
        }
        return this.totalWidth;
    },


    getColumnHeader: function (col) {
        return this.config[col].header;
    },


    setColumnHeader: function (col, header) {
        this.config[col].header = header;
        this.fireEvent("headerchange", this, col, header);
    },


    getColumnTooltip: function (col) {
        return this.config[col].tooltip;
    },

    setColumnTooltip: function (col, tooltip) {
        this.config[col].tooltip = tooltip;
    },


    getDataIndex: function (col) {
        return this.config[col].dataIndex;
    },


    setDataIndex: function (col, dataIndex) {
        this.config[col].dataIndex = dataIndex;
    },


    findColumnIndex: function (dataIndex) {
        var c = this.config;
        for (var i = 0, len = c.length; i < len; i++) {
            if (c[i].dataIndex == dataIndex) {
                return i;
            }
        }
        return -1;
    },


    isCellEditable: function (colIndex, rowIndex) {
        var c = this.config[colIndex],
            ed = c.editable;


        return !!(ed || (!Ext.isDefined(ed) && c.editor));
    },


    getCellEditor: function (colIndex, rowIndex) {
        return this.config[colIndex].getCellEditor(rowIndex);
    },


    setEditable: function (col, editable) {
        this.config[col].editable = editable;
    },


    isHidden: function (colIndex) {
        return !!this.config[colIndex].hidden;
    },


    isFixed: function (colIndex) {
        return !!this.config[colIndex].fixed;
    },


    isResizable: function (colIndex) {
        return colIndex >= 0 && this.config[colIndex].resizable !== false && this.config[colIndex].fixed !== true;
    },


    setHidden: function (colIndex, hidden) {
        var c = this.config[colIndex];
        if (c.hidden !== hidden) {
            c.hidden = hidden;
            this.totalWidth = null;
            this.fireEvent("hiddenchange", this, colIndex, hidden);
        }
    },


    setEditor: function (col, editor) {
        this.config[col].setEditor(editor);
    },


    destroy: function () {
        var length = this.config.length,
            i = 0;

        for (; i < length; i++) {
            this.config[i].destroy();
        }
        delete this.config;
        delete this.lookup;
        this.purgeListeners();
    },


    setState: function (col, state) {
        state = Ext.applyIf(state, this.defaults);
        Ext.apply(this.config[col], state);
    }
});


Ext.grid.ColumnModel.defaultRenderer = function (value) {
    if (typeof value == "string" && value.length < 1) {
        return "&#160;";
    }
    return value;
};
Ext.grid.AbstractSelectionModel = Ext.extend(Ext.util.Observable, {


    constructor: function () {
        this.locked = false;
        Ext.grid.AbstractSelectionModel.superclass.constructor.call(this);
    },


    init: function (grid) {
        this.grid = grid;
        if (this.lockOnInit) {
            delete this.lockOnInit;
            this.locked = false;
            this.lock();
        }
        this.initEvents();
    },


    lock: function () {
        if (!this.locked) {
            this.locked = true;

            var g = this.grid;
            if (g) {
                g.getView().on({
                    scope: this,
                    beforerefresh: this.sortUnLock,
                    refresh: this.sortLock
                });
            } else {
                this.lockOnInit = true;
            }
        }
    },


    sortLock: function () {
        this.locked = true;
    },


    sortUnLock: function () {
        this.locked = false;
    },


    unlock: function () {
        if (this.locked) {
            this.locked = false;
            var g = this.grid,
                gv;


            if (g) {
                gv = g.getView();
                gv.un('beforerefresh', this.sortUnLock, this);
                gv.un('refresh', this.sortLock, this);
            } else {
                delete this.lockOnInit;
            }
        }
    },


    isLocked: function () {
        return this.locked;
    },

    destroy: function () {
        this.unlock();
        this.purgeListeners();
    }
});
Ext.grid.RowSelectionModel = Ext.extend(Ext.grid.AbstractSelectionModel, {

    singleSelect: false,

    constructor: function (config) {
        Ext.apply(this, config);
        this.selections = new Ext.util.MixedCollection(false, function (o) {
            return o.id;
        });

        this.last = false;
        this.lastActive = false;

        this.addEvents(

	        'selectionchange',

	        'beforerowselect',

	        'rowselect',

	        'rowdeselect'
        );
        Ext.grid.RowSelectionModel.superclass.constructor.call(this);
    },



    initEvents: function () {

        if (!this.grid.enableDragDrop && !this.grid.enableDrag) {
            this.grid.on('rowmousedown', this.handleMouseDown, this);
        }

        this.rowNav = new Ext.KeyNav(this.grid.getGridEl(), {
            up: this.onKeyPress,
            down: this.onKeyPress,
            scope: this
        });

        this.grid.getView().on({
            scope: this,
            refresh: this.onRefresh,
            rowupdated: this.onRowUpdated,
            rowremoved: this.onRemove
        });
    },

    onKeyPress: function (e, name) {
        var up = name == 'up',
            method = up ? 'selectPrevious' : 'selectNext',
            add = up ? -1 : 1,
            last;
        if (!e.shiftKey || this.singleSelect) {
            this[method](false);
        } else if (this.last !== false && this.lastActive !== false) {
            last = this.last;
            this.selectRange(this.last, this.lastActive + add);
            this.grid.getView().focusRow(this.lastActive);
            if (last !== false) {
                this.last = last;
            }
        } else {
            this.selectFirstRow();
        }
    },


    onRefresh: function () {
        var ds = this.grid.store,
            s = this.getSelections(),
            i = 0,
            len = s.length,
            index;

        this.silent = true;
        this.clearSelections(true);
        for (; i < len; i++) {
            r = s[i];
            if ((index = ds.indexOfId(r.id)) != -1) {
                this.selectRow(index, true);
            }
        }
        if (s.length != this.selections.getCount()) {
            this.fireEvent('selectionchange', this);
        }
        this.silent = false;
    },


    onRemove: function (v, index, r) {
        if (this.selections.remove(r) !== false) {
            this.fireEvent('selectionchange', this);
        }
    },


    onRowUpdated: function (v, index, r) {
        if (this.isSelected(r)) {
            v.onRowSelect(index);
        }
    },


    selectRecords: function (records, keepExisting) {
        if (!keepExisting) {
            this.clearSelections();
        }
        var ds = this.grid.store,
            i = 0,
            len = records.length;
        for (; i < len; i++) {
            this.selectRow(ds.indexOf(records[i]), true);
        }
    },


    getCount: function () {
        return this.selections.length;
    },


    selectFirstRow: function () {
        this.selectRow(0);
    },


    selectLastRow: function (keepExisting) {
        this.selectRow(this.grid.store.getCount() - 1, keepExisting);
    },


    selectNext: function (keepExisting) {
        if (this.hasNext()) {
            this.selectRow(this.last + 1, keepExisting);
            this.grid.getView().focusRow(this.last);
            return true;
        }
        return false;
    },


    selectPrevious: function (keepExisting) {
        if (this.hasPrevious()) {
            this.selectRow(this.last - 1, keepExisting);
            this.grid.getView().focusRow(this.last);
            return true;
        }
        return false;
    },


    hasNext: function () {
        return this.last !== false && (this.last + 1) < this.grid.store.getCount();
    },


    hasPrevious: function () {
        return !!this.last;
    },



    getSelections: function () {
        return [].concat(this.selections.items);
    },


    getSelected: function () {
        return this.selections.itemAt(0);
    },


    each: function (fn, scope) {
        var s = this.getSelections(),
            i = 0,
            len = s.length;

        for (; i < len; i++) {
            if (fn.call(scope || this, s[i], i) === false) {
                return false;
            }
        }
        return true;
    },


    clearSelections: function (fast) {
        if (this.isLocked()) {
            return;
        }
        if (fast !== true) {
            var ds = this.grid.store,
                s = this.selections;
            s.each(function (r) {
                this.deselectRow(ds.indexOfId(r.id));
            }, this);
            s.clear();
        } else {
            this.selections.clear();
        }
        this.last = false;
    },



    selectAll: function () {
        if (this.isLocked()) {
            return;
        }
        this.selections.clear();
        for (var i = 0, len = this.grid.store.getCount(); i < len; i++) {
            this.selectRow(i, true);
        }
    },


    hasSelection: function () {
        return this.selections.length > 0;
    },


    isSelected: function (index) {
        var r = Ext.isNumber(index) ? this.grid.store.getAt(index) : index;
        return (r && this.selections.key(r.id) ? true : false);
    },


    isIdSelected: function (id) {
        return (this.selections.key(id) ? true : false);
    },


    handleMouseDown: function (g, rowIndex, e) {
        if (e.button !== 0 || this.isLocked()) {
            return;
        }
        var view = this.grid.getView();
        if (e.shiftKey && !this.singleSelect && this.last !== false) {
            var last = this.last;
            this.selectRange(last, rowIndex, e.ctrlKey);
            this.last = last;
            view.focusRow(rowIndex);
        } else {
            var isSelected = this.isSelected(rowIndex);
            if (e.ctrlKey && isSelected) {
                this.deselectRow(rowIndex);
            } else if (!isSelected || this.getCount() > 1) {
                this.selectRow(rowIndex, e.ctrlKey || e.shiftKey);
                view.focusRow(rowIndex);
            }
        }
    },


    selectRows: function (rows, keepExisting) {
        if (!keepExisting) {
            this.clearSelections();
        }
        for (var i = 0, len = rows.length; i < len; i++) {
            this.selectRow(rows[i], true);
        }
    },


    selectRange: function (startRow, endRow, keepExisting) {
        var i;
        if (this.isLocked()) {
            return;
        }
        if (!keepExisting) {
            this.clearSelections();
        }
        if (startRow <= endRow) {
            for (i = startRow; i <= endRow; i++) {
                this.selectRow(i, true);
            }
        } else {
            for (i = startRow; i >= endRow; i--) {
                this.selectRow(i, true);
            }
        }
    },


    deselectRange: function (startRow, endRow, preventViewNotify) {
        if (this.isLocked()) {
            return;
        }
        for (var i = startRow; i <= endRow; i++) {
            this.deselectRow(i, preventViewNotify);
        }
    },


    selectRow: function (index, keepExisting, preventViewNotify) {
        if (this.isLocked() || (index < 0 || index >= this.grid.store.getCount()) || (keepExisting && this.isSelected(index))) {
            return;
        }
        var r = this.grid.store.getAt(index);
        if (r && this.fireEvent('beforerowselect', this, index, keepExisting, r) !== false) {
            if (!keepExisting || this.singleSelect) {
                this.clearSelections();
            }
            this.selections.add(r);
            this.last = this.lastActive = index;
            if (!preventViewNotify) {
                this.grid.getView().onRowSelect(index);
            }
            if (!this.silent) {
                this.fireEvent('rowselect', this, index, r);
                this.fireEvent('selectionchange', this);
            }
        }
    },


    deselectRow: function (index, preventViewNotify) {
        if (this.isLocked()) {
            return;
        }
        if (this.last == index) {
            this.last = false;
        }
        if (this.lastActive == index) {
            this.lastActive = false;
        }
        var r = this.grid.store.getAt(index);
        if (r) {
            this.selections.remove(r);
            if (!preventViewNotify) {
                this.grid.getView().onRowDeselect(index);
            }
            this.fireEvent('rowdeselect', this, index, r);
            this.fireEvent('selectionchange', this);
        }
    },


    acceptsNav: function (row, col, cm) {
        return !cm.isHidden(col) && cm.isCellEditable(col, row);
    },


    onEditorKey: function (field, e) {
        var k = e.getKey(),
            newCell,
            g = this.grid,
            last = g.lastEdit,
            ed = g.activeEditor,
            shift = e.shiftKey,
            ae, last, r, c;

        if (k == e.TAB) {
            e.stopEvent();
            ed.completeEdit();
            if (shift) {
                newCell = g.walkCells(ed.row, ed.col - 1, -1, this.acceptsNav, this);
            } else {
                newCell = g.walkCells(ed.row, ed.col + 1, 1, this.acceptsNav, this);
            }
        } else if (k == e.ENTER) {
            if (this.moveEditorOnEnter !== false) {
                if (shift) {
                    newCell = g.walkCells(last.row - 1, last.col, -1, this.acceptsNav, this);
                } else {
                    newCell = g.walkCells(last.row + 1, last.col, 1, this.acceptsNav, this);
                }
            }
        }
        if (newCell) {
            r = newCell[0];
            c = newCell[1];

            if (last.row != r) {
                this.selectRow(r);
            }

            if (g.isEditor && g.editing) {
                ae = g.activeEditor;
                if (ae && ae.field.triggerBlur) {

                    ae.field.triggerBlur();
                }
            }
            g.startEditing(r, c);
        }
    },

    destroy: function () {
        Ext.destroy(this.rowNav);
        this.rowNav = null;
        Ext.grid.RowSelectionModel.superclass.destroy.call(this);
    }
});
Ext.grid.Column = Ext.extend(Ext.util.Observable, {
























    isColumn: true,

    constructor: function (config) {
        Ext.apply(this, config);

        if (Ext.isString(this.renderer)) {
            this.renderer = Ext.util.Format[this.renderer];
        } else if (Ext.isObject(this.renderer)) {
            this.scope = this.renderer.scope;
            this.renderer = this.renderer.fn;
        }
        if (!this.scope) {
            this.scope = this;
        }

        var ed = this.editor;
        delete this.editor;
        this.setEditor(ed);
        this.addEvents(

            'click',

            'contextmenu',

            'dblclick',

            'mousedown'
        );
        Ext.grid.Column.superclass.constructor.call(this);
    },


    processEvent: function (name, e, grid, rowIndex, colIndex) {
        return this.fireEvent(name, this, grid, rowIndex, e);
    },


    destroy: function () {
        if (this.setEditor) {
            this.setEditor(null);
        }
        this.purgeListeners();
    },


    renderer: function (value) {
        return value;
    },


    getEditor: function (rowIndex) {
        return this.editable !== false ? this.editor : null;
    },


    setEditor: function (editor) {
        var ed = this.editor;
        if (ed) {
            if (ed.gridEditor) {
                ed.gridEditor.destroy();
                delete ed.gridEditor;
            } else {
                ed.destroy();
            }
        }
        this.editor = null;
        if (editor) {

            if (!editor.isXType) {
                editor = Ext.create(editor, 'textfield');
            }
            this.editor = editor;
        }
    },


    getCellEditor: function (rowIndex) {
        var ed = this.getEditor(rowIndex);
        if (ed) {
            if (!ed.startEdit) {
                if (!ed.gridEditor) {
                    ed.gridEditor = new Ext.grid.GridEditor(ed);
                }
                ed = ed.gridEditor;
            }
        }
        return ed;
    }
});


Ext.grid.BooleanColumn = Ext.extend(Ext.grid.Column, {

    trueText: 'true',

    falseText: 'false',

    undefinedText: '&#160;',

    constructor: function (cfg) {
        Ext.grid.BooleanColumn.superclass.constructor.call(this, cfg);
        var t = this.trueText, f = this.falseText, u = this.undefinedText;
        this.renderer = function (v) {
            if (v === undefined) {
                return u;
            }
            if (!v || v === 'false') {
                return f;
            }
            return t;
        };
    }
});


Ext.grid.NumberColumn = Ext.extend(Ext.grid.Column, {

    format: '0,000.00',
    constructor: function (cfg) {
        Ext.grid.NumberColumn.superclass.constructor.call(this, cfg);
        this.renderer = Ext.util.Format.numberRenderer(this.format);
    }
});


Ext.grid.DateColumn = Ext.extend(Ext.grid.Column, {

    format: 'm/d/Y',
    constructor: function (cfg) {
        Ext.grid.DateColumn.superclass.constructor.call(this, cfg);
        this.renderer = Ext.util.Format.dateRenderer(this.format);
    }
});


Ext.grid.TemplateColumn = Ext.extend(Ext.grid.Column, {

    constructor: function (cfg) {
        Ext.grid.TemplateColumn.superclass.constructor.call(this, cfg);
        var tpl = (!Ext.isPrimitive(this.tpl) && this.tpl.compile) ? this.tpl : new Ext.XTemplate(this.tpl);
        this.renderer = function (value, p, r) {
            return tpl.apply(r.data);
        };
        this.tpl = tpl;
    }
});


Ext.grid.ActionColumn = Ext.extend(Ext.grid.Column, {








    header: '&#160;',

    actionIdRe: /x-action-col-(\d+)/,


    altText: '',

    constructor: function (cfg) {
        var me = this,
            items = cfg.items || (me.items = [me]),
            l = items.length,
            i,
            item;

        Ext.grid.ActionColumn.superclass.constructor.call(me, cfg);



        me.renderer = function (v, meta) {

            v = Ext.isFunction(cfg.renderer) ? cfg.renderer.apply(this, arguments) || '' : '';

            meta.css += ' x-action-col-cell';
            for (i = 0; i < l; i++) {
                item = items[i];
                v += '<img alt="' + me.altText + '" src="' + (item.icon || Ext.BLANK_IMAGE_URL) +
                    '" class="x-action-col-icon x-action-col-' + String(i) + ' ' + (item.iconCls || '') +
                    ' ' + (Ext.isFunction(item.getClass) ? item.getClass.apply(item.scope || this.scope || this, arguments) : '') + '"' +
                    ((item.tooltip) ? ' ext:qtip="' + item.tooltip + '"' : '') + ' />';
            }
            return v;
        };
    },

    destroy: function () {
        delete this.items;
        delete this.renderer;
        return Ext.grid.ActionColumn.superclass.destroy.apply(this, arguments);
    },


    processEvent: function (name, e, grid, rowIndex, colIndex) {
        var m = e.getTarget().className.match(this.actionIdRe),
            item, fn;
        if (m && (item = this.items[parseInt(m[1], 10)])) {
            if (name == 'click') {
                (fn = item.handler || this.handler) && fn.call(item.scope || this.scope || this, grid, rowIndex, colIndex, item, e);
            } else if ((name == 'mousedown') && (item.stopSelection !== false)) {
                return false;
            }
        }
        return Ext.grid.ActionColumn.superclass.processEvent.apply(this, arguments);
    }
});


Ext.grid.Column.types = {
    gridcolumn: Ext.grid.Column,
    booleancolumn: Ext.grid.BooleanColumn,
    numbercolumn: Ext.grid.NumberColumn,
    datecolumn: Ext.grid.DateColumn,
    templatecolumn: Ext.grid.TemplateColumn,
    actioncolumn: Ext.grid.ActionColumn
};
Ext.grid.RowNumberer = Ext.extend(Object, {

    header: "",

    width: 23,

    sortable: false,

    constructor: function (config) {
        Ext.apply(this, config);
        if (this.rowspan) {
            this.renderer = this.renderer.createDelegate(this);
        }
    },


    fixed: true,
    hideable: false,
    menuDisabled: true,
    dataIndex: '',
    id: 'numberer',
    rowspan: undefined,


    renderer: function (v, p, record, rowIndex) {
        if (this.rowspan) {
            p.cellAttr = 'rowspan="' + this.rowspan + '"';
        }
        return rowIndex + 1;
    }
});
Ext.grid.CheckboxSelectionModel = Ext.extend(Ext.grid.RowSelectionModel, {



    header: '<div class="x-grid3-hd-checker">&#160;</div>',

    width: 20,

    sortable: false,


    menuDisabled: true,
    fixed: true,
    hideable: false,
    dataIndex: '',
    id: 'checker',
    isColumn: true,

    constructor: function () {
        Ext.grid.CheckboxSelectionModel.superclass.constructor.apply(this, arguments);
        if (this.checkOnly) {
            this.handleMouseDown = Ext.emptyFn;
        }
    },


    initEvents: function () {
        Ext.grid.CheckboxSelectionModel.superclass.initEvents.call(this);
        this.grid.on('render', function () {
            Ext.fly(this.grid.getView().innerHd).on('mousedown', this.onHdMouseDown, this);
        }, this);
    },


    processEvent: function (name, e, grid, rowIndex, colIndex) {
        if (name == 'mousedown') {
            this.onMouseDown(e, e.getTarget());
            return false;
        } else {
            return Ext.grid.Column.prototype.processEvent.apply(this, arguments);
        }
    },


    onMouseDown: function (e, t) {
        if (e.button === 0 && t.className == 'x-grid3-row-checker') {
            e.stopEvent();
            var row = e.getTarget('.x-grid3-row');
            if (row) {
                var index = row.rowIndex;
                if (this.isSelected(index)) {
                    this.deselectRow(index);
                } else {
                    this.selectRow(index, true);
                    this.grid.getView().focusRow(index);
                }
            }
        }
    },


    onHdMouseDown: function (e, t) {
        if (t.className == 'x-grid3-hd-checker') {
            e.stopEvent();
            var hd = Ext.fly(t.parentNode);
            var isChecked = hd.hasClass('x-grid3-hd-checker-on');
            if (isChecked) {
                hd.removeClass('x-grid3-hd-checker-on');
                this.clearSelections();
            } else {
                hd.addClass('x-grid3-hd-checker-on');
                this.selectAll();
            }
        }
    },


    renderer: function (v, p, record) {
        return '<div class="x-grid3-row-checker">&#160;</div>';
    }
});
Ext.grid.CellSelectionModel = Ext.extend(Ext.grid.AbstractSelectionModel, {

    constructor: function (config) {
        Ext.apply(this, config);

        this.selection = null;

        this.addEvents(

	        "beforecellselect",

	        "cellselect",

	        "selectionchange"
	    );

        Ext.grid.CellSelectionModel.superclass.constructor.call(this);
    },


    initEvents: function () {
        this.grid.on('cellmousedown', this.handleMouseDown, this);
        this.grid.on(Ext.EventManager.getKeyEvent(), this.handleKeyDown, this);
        this.grid.getView().on({
            scope: this,
            refresh: this.onViewChange,
            rowupdated: this.onRowUpdated,
            beforerowremoved: this.clearSelections,
            beforerowsinserted: this.clearSelections
        });
        if (this.grid.isEditor) {
            this.grid.on('beforeedit', this.beforeEdit, this);
        }
    },


    beforeEdit: function (e) {
        this.select(e.row, e.column, false, true, e.record);
    },


    onRowUpdated: function (v, index, r) {
        if (this.selection && this.selection.record == r) {
            v.onCellSelect(index, this.selection.cell[1]);
        }
    },


    onViewChange: function () {
        this.clearSelections(true);
    },


    getSelectedCell: function () {
        return this.selection ? this.selection.cell : null;
    },


    clearSelections: function (preventNotify) {
        var s = this.selection;
        if (s) {
            if (preventNotify !== true) {
                this.grid.view.onCellDeselect(s.cell[0], s.cell[1]);
            }
            this.selection = null;
            this.fireEvent("selectionchange", this, null);
        }
    },


    hasSelection: function () {
        return this.selection ? true : false;
    },


    handleMouseDown: function (g, row, cell, e) {
        if (e.button !== 0 || this.isLocked()) {
            return;
        }
        this.select(row, cell);
    },


    select: function (rowIndex, colIndex, preventViewNotify, preventFocus, r) {
        if (this.fireEvent("beforecellselect", this, rowIndex, colIndex) !== false) {
            this.clearSelections();
            r = r || this.grid.store.getAt(rowIndex);
            this.selection = {
                record: r,
                cell: [rowIndex, colIndex]
            };
            if (!preventViewNotify) {
                var v = this.grid.getView();
                v.onCellSelect(rowIndex, colIndex);
                if (preventFocus !== true) {
                    v.focusCell(rowIndex, colIndex);
                }
            }
            this.fireEvent("cellselect", this, rowIndex, colIndex);
            this.fireEvent("selectionchange", this, this.selection);
        }
    },


    isSelectable: function (rowIndex, colIndex, cm) {
        return !cm.isHidden(colIndex);
    },


    onEditorKey: function (field, e) {
        if (e.getKey() == e.TAB) {
            this.handleKeyDown(e);
        }
    },


    handleKeyDown: function (e) {
        if (!e.isNavKeyPress()) {
            return;
        }

        var k = e.getKey(),
            g = this.grid,
            s = this.selection,
            sm = this,
            walk = function (row, col, step) {
                return g.walkCells(
                    row,
                    col,
                    step,
                    g.isEditor && g.editing ? sm.acceptsNav : sm.isSelectable,
                    sm
                );
            },
            cell, newCell, r, c, ae;

        switch (k) {
            case e.ESC:
            case e.PAGE_UP:
            case e.PAGE_DOWN:

                break;
            default:

                e.stopEvent();
                break;
        }

        if (!s) {
            cell = walk(0, 0, 1);
            if (cell) {
                this.select(cell[0], cell[1]);
            }
            return;
        }

        cell = s.cell;
        r = cell[0];
        c = cell[1];

        switch (k) {
            case e.TAB:
                if (e.shiftKey) {
                    newCell = walk(r, c - 1, -1);
                } else {
                    newCell = walk(r, c + 1, 1);
                }
                break;
            case e.DOWN:
                newCell = walk(r + 1, c, 1);
                break;
            case e.UP:
                newCell = walk(r - 1, c, -1);
                break;
            case e.RIGHT:
                newCell = walk(r, c + 1, 1);
                break;
            case e.LEFT:
                newCell = walk(r, c - 1, -1);
                break;
            case e.ENTER:
                if (g.isEditor && !g.editing) {
                    g.startEditing(r, c);
                    return;
                }
                break;
        }

        if (newCell) {

            r = newCell[0];
            c = newCell[1];

            this.select(r, c);

            if (g.isEditor && g.editing) {
                ae = g.activeEditor;
                if (ae && ae.field.triggerBlur) {

                    ae.field.triggerBlur();
                }
                g.startEditing(r, c);
            }
        }
    },

    acceptsNav: function (row, col, cm) {
        return !cm.isHidden(col) && cm.isCellEditable(col, row);
    }
});
Ext.grid.EditorGridPanel = Ext.extend(Ext.grid.GridPanel, {

    clicksToEdit: 2,


    forceValidation: false,


    isEditor: true,

    detectEdit: false,


    autoEncode: false,



    trackMouseOver: false,


    initComponent: function () {
        Ext.grid.EditorGridPanel.superclass.initComponent.call(this);

        if (!this.selModel) {

            this.selModel = new Ext.grid.CellSelectionModel();
        }

        this.activeEditor = null;

        this.addEvents(

            "beforeedit",

            "afteredit",

            "validateedit"
        );
    },


    initEvents: function () {
        Ext.grid.EditorGridPanel.superclass.initEvents.call(this);

        this.getGridEl().on('mousewheel', this.stopEditing.createDelegate(this, [true]), this);
        this.on('columnresize', this.stopEditing, this, [true]);

        if (this.clicksToEdit == 1) {
            this.on("cellclick", this.onCellDblClick, this);
        } else {
            var view = this.getView();
            if (this.clicksToEdit == 'auto' && view.mainBody) {
                view.mainBody.on('mousedown', this.onAutoEditClick, this);
            }
            this.on('celldblclick', this.onCellDblClick, this);
        }
    },

    onResize: function () {
        Ext.grid.EditorGridPanel.superclass.onResize.apply(this, arguments);
        var ae = this.activeEditor;
        if (this.editing && ae) {
            ae.realign(true);
        }
    },


    onCellDblClick: function (g, row, col) {
        this.startEditing(row, col);
    },


    onAutoEditClick: function (e, t) {
        if (e.button !== 0) {
            return;
        }
        var row = this.view.findRowIndex(t),
            col = this.view.findCellIndex(t);
        if (row !== false && col !== false) {
            this.stopEditing();
            if (this.selModel.getSelectedCell) {
                var sc = this.selModel.getSelectedCell();
                if (sc && sc[0] === row && sc[1] === col) {
                    this.startEditing(row, col);
                }
            } else {
                if (this.selModel.isSelected(row)) {
                    this.startEditing(row, col);
                }
            }
        }
    },


    onEditComplete: function (ed, value, startValue) {
        this.editing = false;
        this.lastActiveEditor = this.activeEditor;
        this.activeEditor = null;

        var r = ed.record,
            field = this.colModel.getDataIndex(ed.col);
        value = this.postEditValue(value, startValue, r, field);
        if (this.forceValidation === true || String(value) !== String(startValue)) {
            var e = {
                grid: this,
                record: r,
                field: field,
                originalValue: startValue,
                value: value,
                row: ed.row,
                column: ed.col,
                cancel: false
            };
            if (this.fireEvent("validateedit", e) !== false && !e.cancel && String(value) !== String(startValue)) {
                r.set(field, e.value);
                delete e.cancel;
                this.fireEvent("afteredit", e);
            }
        }
        this.view.focusCell(ed.row, ed.col);
    },


    startEditing: function (row, col) {
        this.stopEditing();
        if (this.colModel.isCellEditable(col, row)) {
            this.view.ensureVisible(row, col, true);
            var r = this.store.getAt(row),
                field = this.colModel.getDataIndex(col),
                e = {
                    grid: this,
                    record: r,
                    field: field,
                    value: r.data[field],
                    row: row,
                    column: col,
                    cancel: false
                };
            if (this.fireEvent("beforeedit", e) !== false && !e.cancel) {
                this.editing = true;
                var ed = this.colModel.getCellEditor(col, row);
                if (!ed) {
                    return;
                }
                if (!ed.rendered) {
                    ed.parentEl = this.view.getEditorParent(ed);
                    ed.on({
                        scope: this,
                        render: {
                            fn: function (c) {
                                c.field.focus(false, true);
                            },
                            single: true,
                            scope: this
                        },
                        specialkey: function (field, e) {
                            this.getSelectionModel().onEditorKey(field, e);
                        },
                        complete: this.onEditComplete,
                        canceledit: this.stopEditing.createDelegate(this, [true])
                    });
                }
                Ext.apply(ed, {
                    row: row,
                    col: col,
                    record: r
                });
                this.lastEdit = {
                    row: row,
                    col: col
                };
                this.activeEditor = ed;


                ed.selectSameEditor = (this.activeEditor == this.lastActiveEditor);
                var v = this.preEditValue(r, field);
                ed.startEdit(this.view.getCell(row, col).firstChild, Ext.isDefined(v) ? v : '');


                (function () {
                    delete ed.selectSameEditor;
                }).defer(50);
            }
        }
    },


    preEditValue: function (r, field) {
        var value = r.data[field];
        return this.autoEncode && Ext.isString(value) ? Ext.util.Format.htmlDecode(value) : value;
    },


    postEditValue: function (value, originalValue, r, field) {
        return this.autoEncode && Ext.isString(value) ? Ext.util.Format.htmlEncode(value) : value;
    },


    stopEditing: function (cancel) {
        if (this.editing) {

            var ae = this.lastActiveEditor = this.activeEditor;
            if (ae) {
                ae[cancel === true ? 'cancelEdit' : 'completeEdit']();
                this.view.focusCell(ae.row, ae.col);
            }
            this.activeEditor = null;
        }
        this.editing = false;
    }
});
Ext.reg('editorgrid', Ext.grid.EditorGridPanel);

Ext.grid.GridEditor = function (field, config) {
    Ext.grid.GridEditor.superclass.constructor.call(this, field, config);
    field.monitorTab = false;
};

Ext.extend(Ext.grid.GridEditor, Ext.Editor, {
    alignment: "tl-tl",
    autoSize: "width",
    hideEl: false,
    cls: "x-small-editor x-grid-editor",
    shim: false,
    shadow: false
});
Ext.grid.PropertyRecord = Ext.data.Record.create([
    { name: 'name', type: 'string' }, 'value'
]);


Ext.grid.PropertyStore = Ext.extend(Ext.util.Observable, {

    constructor: function (grid, source) {
        this.grid = grid;
        this.store = new Ext.data.Store({
            recordType: Ext.grid.PropertyRecord
        });
        this.store.on('update', this.onUpdate, this);
        if (source) {
            this.setSource(source);
        }
        Ext.grid.PropertyStore.superclass.constructor.call(this);
    },


    setSource: function (o) {
        this.source = o;
        this.store.removeAll();
        var data = [];
        for (var k in o) {
            if (this.isEditableValue(o[k])) {
                data.push(new Ext.grid.PropertyRecord({ name: k, value: o[k] }, k));
            }
        }
        this.store.loadRecords({ records: data }, {}, true);
    },


    onUpdate: function (ds, record, type) {
        if (type == Ext.data.Record.EDIT) {
            var v = record.data.value;
            var oldValue = record.modified.value;
            if (this.grid.fireEvent('beforepropertychange', this.source, record.id, v, oldValue) !== false) {
                this.source[record.id] = v;
                record.commit();
                this.grid.fireEvent('propertychange', this.source, record.id, v, oldValue);
            } else {
                record.reject();
            }
        }
    },


    getProperty: function (row) {
        return this.store.getAt(row);
    },


    isEditableValue: function (val) {
        return Ext.isPrimitive(val) || Ext.isDate(val);
    },


    setValue: function (prop, value, create) {
        var r = this.getRec(prop);
        if (r) {
            r.set('value', value);
            this.source[prop] = value;
        } else if (create) {

            this.source[prop] = value;
            r = new Ext.grid.PropertyRecord({ name: prop, value: value }, prop);
            this.store.add(r);

        }
    },


    remove: function (prop) {
        var r = this.getRec(prop);
        if (r) {
            this.store.remove(r);
            delete this.source[prop];
        }
    },


    getRec: function (prop) {
        return this.store.getById(prop);
    },


    getSource: function () {
        return this.source;
    }
});


Ext.grid.PropertyColumnModel = Ext.extend(Ext.grid.ColumnModel, {

    nameText: 'Name',
    valueText: 'Value',
    dateFormat: 'm/j/Y',
    trueText: 'true',
    falseText: 'false',

    constructor: function (grid, store) {
        var g = Ext.grid,
	        f = Ext.form;

        this.grid = grid;
        g.PropertyColumnModel.superclass.constructor.call(this, [
	        { header: this.nameText, width: 50, sortable: true, dataIndex: 'name', id: 'name', menuDisabled: true },
	        { header: this.valueText, width: 50, resizable: false, dataIndex: 'value', id: 'value', menuDisabled: true }
	    ]);
        this.store = store;

        var bfield = new f.Field({
            autoCreate: { tag: 'select', children: [
	            { tag: 'option', value: 'true', html: this.trueText },
	            { tag: 'option', value: 'false', html: this.falseText }
	        ]
            },
            getValue: function () {
                return this.el.dom.value == 'true';
            }
        });
        this.editors = {
            'date': new g.GridEditor(new f.DateField({ selectOnFocus: true })),
            'string': new g.GridEditor(new f.TextField({ selectOnFocus: true })),
            'number': new g.GridEditor(new f.NumberField({ selectOnFocus: true, style: 'text-align:left;' })),
            'boolean': new g.GridEditor(bfield, {
                autoSize: 'both'
            })
        };
        this.renderCellDelegate = this.renderCell.createDelegate(this);
        this.renderPropDelegate = this.renderProp.createDelegate(this);
    },


    renderDate: function (dateVal) {
        return dateVal.dateFormat(this.dateFormat);
    },


    renderBool: function (bVal) {
        return this[bVal ? 'trueText' : 'falseText'];
    },


    isCellEditable: function (colIndex, rowIndex) {
        return colIndex == 1;
    },


    getRenderer: function (col) {
        return col == 1 ?
            this.renderCellDelegate : this.renderPropDelegate;
    },


    renderProp: function (v) {
        return this.getPropertyName(v);
    },


    renderCell: function (val, meta, rec) {
        var renderer = this.grid.customRenderers[rec.get('name')];
        if (renderer) {
            return renderer.apply(this, arguments);
        }
        var rv = val;
        if (Ext.isDate(val)) {
            rv = this.renderDate(val);
        } else if (typeof val == 'boolean') {
            rv = this.renderBool(val);
        }
        return Ext.util.Format.htmlEncode(rv);
    },


    getPropertyName: function (name) {
        var pn = this.grid.propertyNames;
        return pn && pn[name] ? pn[name] : name;
    },


    getCellEditor: function (colIndex, rowIndex) {
        var p = this.store.getProperty(rowIndex),
            n = p.data.name,
            val = p.data.value;
        if (this.grid.customEditors[n]) {
            return this.grid.customEditors[n];
        }
        if (Ext.isDate(val)) {
            return this.editors.date;
        } else if (typeof val == 'number') {
            return this.editors.number;
        } else if (typeof val == 'boolean') {
            return this.editors['boolean'];
        } else {
            return this.editors.string;
        }
    },


    destroy: function () {
        Ext.grid.PropertyColumnModel.superclass.destroy.call(this);
        this.destroyEditors(this.editors);
        this.destroyEditors(this.grid.customEditors);
    },

    destroyEditors: function (editors) {
        for (var ed in editors) {
            Ext.destroy(editors[ed]);
        }
    }
});


Ext.grid.PropertyGrid = Ext.extend(Ext.grid.EditorGridPanel, {







    enableColumnMove: false,
    stripeRows: false,
    trackMouseOver: false,
    clicksToEdit: 1,
    enableHdMenu: false,
    viewConfig: {
        forceFit: true
    },


    initComponent: function () {
        this.customRenderers = this.customRenderers || {};
        this.customEditors = this.customEditors || {};
        this.lastEditRow = null;
        var store = new Ext.grid.PropertyStore(this);
        this.propStore = store;
        var cm = new Ext.grid.PropertyColumnModel(this, store);
        store.store.sort('name', 'ASC');
        this.addEvents(

            'beforepropertychange',

            'propertychange'
        );
        this.cm = cm;
        this.ds = store.store;
        Ext.grid.PropertyGrid.superclass.initComponent.call(this);

        this.mon(this.selModel, 'beforecellselect', function (sm, rowIndex, colIndex) {
            if (colIndex === 0) {
                this.startEditing.defer(200, this, [rowIndex, 1]);
                return false;
            }
        }, this);
    },


    onRender: function () {
        Ext.grid.PropertyGrid.superclass.onRender.apply(this, arguments);

        this.getGridEl().addClass('x-props-grid');
    },


    afterRender: function () {
        Ext.grid.PropertyGrid.superclass.afterRender.apply(this, arguments);
        if (this.source) {
            this.setSource(this.source);
        }
    },


    setSource: function (source) {
        this.propStore.setSource(source);
    },


    getSource: function () {
        return this.propStore.getSource();
    },


    setProperty: function (prop, value, create) {
        this.propStore.setValue(prop, value, create);
    },


    removeProperty: function (prop) {
        this.propStore.remove(prop);
    }





});
Ext.reg("propertygrid", Ext.grid.PropertyGrid);

Ext.grid.GroupingView = Ext.extend(Ext.grid.GridView, {


    groupByText: 'Group By This Field',

    showGroupsText: 'Show in Groups',

    hideGroupedColumn: false,

    showGroupName: true,

    startCollapsed: false,

    enableGrouping: true,

    enableGroupingMenu: true,

    enableNoGroups: true,

    emptyGroupText: '(None)',

    ignoreAdd: false,

    groupTextTpl: '{text}',


    groupMode: 'value',




    cancelEditOnToggle: true,


    initTemplates: function () {
        Ext.grid.GroupingView.superclass.initTemplates.call(this);
        this.state = {};

        var sm = this.grid.getSelectionModel();
        sm.on(sm.selectRow ? 'beforerowselect' : 'beforecellselect',
                this.onBeforeRowSelect, this);

        if (!this.startGroup) {
            this.startGroup = new Ext.XTemplate(
                '<div id="{groupId}" class="x-grid-group {cls}">',
                    '<div id="{groupId}-hd" class="x-grid-group-hd" style="{style}"><div class="x-grid-group-title">', this.groupTextTpl, '</div></div>',
                    '<div id="{groupId}-bd" class="x-grid-group-body">'
            );
        }
        this.startGroup.compile();

        if (!this.endGroup) {
            this.endGroup = '</div></div>';
        }
    },


    findGroup: function (el) {
        return Ext.fly(el).up('.x-grid-group', this.mainBody.dom);
    },


    getGroups: function () {
        return this.hasRows() ? this.mainBody.dom.childNodes : [];
    },


    onAdd: function (ds, records, index) {
        if (this.canGroup() && !this.ignoreAdd) {
            var ss = this.getScrollState();
            this.fireEvent('beforerowsinserted', ds, index, index + (records.length - 1));
            this.refresh();
            this.restoreScroll(ss);
            this.fireEvent('rowsinserted', ds, index, index + (records.length - 1));
        } else if (!this.canGroup()) {
            Ext.grid.GroupingView.superclass.onAdd.apply(this, arguments);
        }
    },


    onRemove: function (ds, record, index, isUpdate) {
        Ext.grid.GroupingView.superclass.onRemove.apply(this, arguments);
        var g = document.getElementById(record._groupId);
        if (g && g.childNodes[1].childNodes.length < 1) {
            Ext.removeNode(g);
        }
        this.applyEmptyText();
    },


    refreshRow: function (record) {
        if (this.ds.getCount() == 1) {
            this.refresh();
        } else {
            this.isUpdating = true;
            Ext.grid.GroupingView.superclass.refreshRow.apply(this, arguments);
            this.isUpdating = false;
        }
    },


    beforeMenuShow: function () {
        var item, items = this.hmenu.items, disabled = this.cm.config[this.hdCtxIndex].groupable === false;
        if ((item = items.get('groupBy'))) {
            item.setDisabled(disabled);
        }
        if ((item = items.get('showGroups'))) {
            item.setDisabled(disabled);
            item.setChecked(this.canGroup(), true);
        }
    },


    renderUI: function () {
        var markup = Ext.grid.GroupingView.superclass.renderUI.call(this);

        if (this.enableGroupingMenu && this.hmenu) {
            this.hmenu.add('-', {
                itemId: 'groupBy',
                text: this.groupByText,
                handler: this.onGroupByClick,
                scope: this,
                iconCls: 'x-group-by-icon'
            });
            if (this.enableNoGroups) {
                this.hmenu.add({
                    itemId: 'showGroups',
                    text: this.showGroupsText,
                    checked: true,
                    checkHandler: this.onShowGroupsClick,
                    scope: this
                });
            }
            this.hmenu.on('beforeshow', this.beforeMenuShow, this);
        }
        return markup;
    },

    processEvent: function (name, e) {
        Ext.grid.GroupingView.superclass.processEvent.call(this, name, e);
        var hd = e.getTarget('.x-grid-group-hd', this.mainBody);
        if (hd) {

            var field = this.getGroupField(),
                prefix = this.getPrefix(field),
                groupValue = hd.id.substring(prefix.length),
                emptyRe = new RegExp('gp-' + Ext.escapeRe(field) + '--hd');


            groupValue = groupValue.substr(0, groupValue.length - 3);


            if (groupValue || emptyRe.test(hd.id)) {
                this.grid.fireEvent('group' + name, this.grid, field, groupValue, e);
            }
            if (name == 'mousedown' && e.button == 0) {
                this.toggleGroup(hd.parentNode);
            }
        }

    },


    onGroupByClick: function () {
        this.enableGrouping = true;
        this.grid.store.groupBy(this.cm.getDataIndex(this.hdCtxIndex));
        this.grid.fireEvent('groupchange', this, this.grid.store.getGroupState());
        this.beforeMenuShow();
        this.refresh();
    },


    onShowGroupsClick: function (mi, checked) {
        this.enableGrouping = checked;
        if (checked) {
            this.onGroupByClick();
        } else {
            this.grid.store.clearGrouping();
            this.grid.fireEvent('groupchange', this, null);
        }
    },


    toggleRowIndex: function (rowIndex, expanded) {
        if (!this.canGroup()) {
            return;
        }
        var row = this.getRow(rowIndex);
        if (row) {
            this.toggleGroup(this.findGroup(row), expanded);
        }
    },


    toggleGroup: function (group, expanded) {
        var gel = Ext.get(group);
        expanded = Ext.isDefined(expanded) ? expanded : gel.hasClass('x-grid-group-collapsed');
        if (this.state[gel.id] !== expanded) {
            if (this.cancelEditOnToggle !== false) {
                this.grid.stopEditing(true);
            }
            this.state[gel.id] = expanded;
            gel[expanded ? 'removeClass' : 'addClass']('x-grid-group-collapsed');
        }
    },


    toggleAllGroups: function (expanded) {
        var groups = this.getGroups();
        for (var i = 0, len = groups.length; i < len; i++) {
            this.toggleGroup(groups[i], expanded);
        }
    },


    expandAllGroups: function () {
        this.toggleAllGroups(true);
    },


    collapseAllGroups: function () {
        this.toggleAllGroups(false);
    },


    getGroup: function (v, r, groupRenderer, rowIndex, colIndex, ds) {
        var column = this.cm.config[colIndex],
            g = groupRenderer ? groupRenderer.call(column.scope, v, {}, r, rowIndex, colIndex, ds) : String(v);
        if (g === '' || g === '&#160;') {
            g = column.emptyGroupText || this.emptyGroupText;
        }
        return g;
    },


    getGroupField: function () {
        return this.grid.store.getGroupState();
    },


    afterRender: function () {
        if (!this.ds || !this.cm) {
            return;
        }
        Ext.grid.GroupingView.superclass.afterRender.call(this);
        if (this.grid.deferRowRender) {
            this.updateGroupWidths();
        }
    },

    afterRenderUI: function () {
        Ext.grid.GroupingView.superclass.afterRenderUI.call(this);

        if (this.enableGroupingMenu && this.hmenu) {
            this.hmenu.add('-', {
                itemId: 'groupBy',
                text: this.groupByText,
                handler: this.onGroupByClick,
                scope: this,
                iconCls: 'x-group-by-icon'
            });

            if (this.enableNoGroups) {
                this.hmenu.add({
                    itemId: 'showGroups',
                    text: this.showGroupsText,
                    checked: true,
                    checkHandler: this.onShowGroupsClick,
                    scope: this
                });
            }

            this.hmenu.on('beforeshow', this.beforeMenuShow, this);
        }
    },


    renderRows: function () {
        var groupField = this.getGroupField();
        var eg = !!groupField;

        if (this.hideGroupedColumn) {
            var colIndex = this.cm.findColumnIndex(groupField),
                hasLastGroupField = Ext.isDefined(this.lastGroupField);
            if (!eg && hasLastGroupField) {
                this.mainBody.update('');
                this.cm.setHidden(this.cm.findColumnIndex(this.lastGroupField), false);
                delete this.lastGroupField;
            } else if (eg && !hasLastGroupField) {
                this.lastGroupField = groupField;
                this.cm.setHidden(colIndex, true);
            } else if (eg && hasLastGroupField && groupField !== this.lastGroupField) {
                this.mainBody.update('');
                var oldIndex = this.cm.findColumnIndex(this.lastGroupField);
                this.cm.setHidden(oldIndex, false);
                this.lastGroupField = groupField;
                this.cm.setHidden(colIndex, true);
            }
        }
        return Ext.grid.GroupingView.superclass.renderRows.apply(
                    this, arguments);
    },


    doRender: function (cs, rs, ds, startRow, colCount, stripe) {
        if (rs.length < 1) {
            return '';
        }

        if (!this.canGroup() || this.isUpdating) {
            return Ext.grid.GroupingView.superclass.doRender.apply(this, arguments);
        }

        var groupField = this.getGroupField(),
            colIndex = this.cm.findColumnIndex(groupField),
            g,
            gstyle = 'width:' + this.getTotalWidth() + ';',
            cfg = this.cm.config[colIndex],
            groupRenderer = cfg.groupRenderer || cfg.renderer,
            prefix = this.showGroupName ? (cfg.groupName || cfg.header) + ': ' : '',
            groups = [],
            curGroup, i, len, gid;

        for (i = 0, len = rs.length; i < len; i++) {
            var rowIndex = startRow + i,
                r = rs[i],
                gvalue = r.data[groupField];

            g = this.getGroup(gvalue, r, groupRenderer, rowIndex, colIndex, ds);
            if (!curGroup || curGroup.group != g) {
                gid = this.constructId(gvalue, groupField, colIndex);


                this.state[gid] = !(Ext.isDefined(this.state[gid]) ? !this.state[gid] : this.startCollapsed);
                curGroup = {
                    group: g,
                    gvalue: gvalue,
                    text: prefix + g,
                    groupId: gid,
                    startRow: rowIndex,
                    rs: [r],
                    cls: this.state[gid] ? '' : 'x-grid-group-collapsed',
                    style: gstyle
                };
                groups.push(curGroup);
            } else {
                curGroup.rs.push(r);
            }
            r._groupId = gid;
        }

        var buf = [];
        for (i = 0, len = groups.length; i < len; i++) {
            g = groups[i];
            this.doGroupStart(buf, g, cs, ds, colCount);
            buf[buf.length] = Ext.grid.GroupingView.superclass.doRender.call(
                    this, cs, g.rs, ds, g.startRow, colCount, stripe);

            this.doGroupEnd(buf, g, cs, ds, colCount);
        }
        return buf.join('');
    },


    getGroupId: function (value) {
        var field = this.getGroupField();
        return this.constructId(value, field, this.cm.findColumnIndex(field));
    },


    constructId: function (value, field, idx) {
        var cfg = this.cm.config[idx],
            groupRenderer = cfg.groupRenderer || cfg.renderer,
            val = (this.groupMode == 'value') ? value : this.getGroup(value, { data: {} }, groupRenderer, 0, idx, this.ds);

        return this.getPrefix(field) + Ext.util.Format.htmlEncode(val);
    },


    canGroup: function () {
        return this.enableGrouping && !!this.getGroupField();
    },


    getPrefix: function (field) {
        return this.grid.getGridEl().id + '-gp-' + field + '-';
    },


    doGroupStart: function (buf, g, cs, ds, colCount) {
        buf[buf.length] = this.startGroup.apply(g);
    },


    doGroupEnd: function (buf, g, cs, ds, colCount) {
        buf[buf.length] = this.endGroup;
    },


    getRows: function () {
        if (!this.canGroup()) {
            return Ext.grid.GroupingView.superclass.getRows.call(this);
        }
        var r = [],
            gs = this.getGroups(),
            g,
            i = 0,
            len = gs.length,
            j,
            jlen;
        for (; i < len; ++i) {
            g = gs[i].childNodes[1];
            if (g) {
                g = g.childNodes;
                for (j = 0, jlen = g.length; j < jlen; ++j) {
                    r[r.length] = g[j];
                }
            }
        }
        return r;
    },


    updateGroupWidths: function () {
        if (!this.canGroup() || !this.hasRows()) {
            return;
        }
        var tw = Math.max(this.cm.getTotalWidth(), this.el.dom.offsetWidth - this.getScrollOffset()) + 'px';
        var gs = this.getGroups();
        for (var i = 0, len = gs.length; i < len; i++) {
            gs[i].firstChild.style.width = tw;
        }
    },


    onColumnWidthUpdated: function (col, w, tw) {
        Ext.grid.GroupingView.superclass.onColumnWidthUpdated.call(this, col, w, tw);
        this.updateGroupWidths();
    },


    onAllColumnWidthsUpdated: function (ws, tw) {
        Ext.grid.GroupingView.superclass.onAllColumnWidthsUpdated.call(this, ws, tw);
        this.updateGroupWidths();
    },


    onColumnHiddenUpdated: function (col, hidden, tw) {
        Ext.grid.GroupingView.superclass.onColumnHiddenUpdated.call(this, col, hidden, tw);
        this.updateGroupWidths();
    },


    onLayout: function () {
        this.updateGroupWidths();
    },


    onBeforeRowSelect: function (sm, rowIndex) {
        this.toggleRowIndex(rowIndex, true);
    }
});

Ext.grid.GroupingView.GROUP_ID = 1000;
